ReactOS  0.4.15-dev-2704-gd5265b0
fat.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS kernel
4  * FILE: drivers/filesystems/fastfat/fat.c
5  * PURPOSE: FastFAT Filesystem
6  * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
7  * Pierre Schweitzer (pierre@reactos.org)
8  *
9  */
10 
11 /* INCLUDES *****************************************************************/
12 
13 #include "vfat.h"
14 
15 #define NDEBUG
16 #include <debug.h>
17 
18 /* GLOBALS ******************************************************************/
19 
20 #define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->FatInfo.BytesPerCluster > PAGE_SIZE ? \
21  (pDeviceExt)->FatInfo.BytesPerCluster : PAGE_SIZE)
22 
23 /* FUNCTIONS ****************************************************************/
24 
25 /*
26  * FUNCTION: Retrieve the next FAT32 cluster from the FAT table via a physical
27  * disk read
28  */
31  PDEVICE_EXTENSION DeviceExt,
32  ULONG CurrentCluster,
34 {
37  ULONG FATOffset;
39  PVOID Context = NULL;
41 
42  ChunkSize = CACHEPAGESIZE(DeviceExt);
43  FATOffset = CurrentCluster * sizeof(ULONG);
44  Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize);
45  _SEH2_TRY
46  {
47  if (!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, MAP_WAIT, &Context, &BaseAddress))
48  {
50  return STATUS_UNSUCCESSFUL;
51  }
52  }
54  {
56  }
57  _SEH2_END;
58 
59  CurrentCluster = (*(PULONG)((char*)BaseAddress + (FATOffset % ChunkSize))) & 0x0fffffff;
60  if (CurrentCluster >= 0xffffff8 && CurrentCluster <= 0xfffffff)
61  CurrentCluster = 0xffffffff;
62 
63  if (CurrentCluster == 0)
64  {
65  DPRINT1("WARNING: File system corruption detected. You may need to run a disk repair utility.\n");
68  ASSERT(CurrentCluster != 0);
69  }
71  *NextCluster = CurrentCluster;
72  return Status;
73 }
74 
75 /*
76  * FUNCTION: Retrieve the next FAT16 cluster from the FAT table
77  */
80  PDEVICE_EXTENSION DeviceExt,
81  ULONG CurrentCluster,
83 {
86  ULONG FATOffset;
88  PVOID Context;
90 
91  ChunkSize = CACHEPAGESIZE(DeviceExt);
92  FATOffset = CurrentCluster * 2;
93  Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize);
94  _SEH2_TRY
95  {
96  CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, MAP_WAIT, &Context, &BaseAddress);
97  }
99  {
101  }
102  _SEH2_END;
103 
104  CurrentCluster = *((PUSHORT)((char*)BaseAddress + (FATOffset % ChunkSize)));
105  if (CurrentCluster >= 0xfff8 && CurrentCluster <= 0xffff)
106  CurrentCluster = 0xffffffff;
107 
108  if (CurrentCluster == 0)
109  {
110  DPRINT1("WARNING: File system corruption detected. You may need to run a disk repair utility.\n");
113  ASSERT(CurrentCluster != 0);
114  }
115 
117  *NextCluster = CurrentCluster;
118  return Status;
119 }
120 
121 /*
122  * FUNCTION: Retrieve the next FAT12 cluster from the FAT table
123  */
124 NTSTATUS
126  PDEVICE_EXTENSION DeviceExt,
127  ULONG CurrentCluster,
129 {
130  PUSHORT CBlock;
131  ULONG Entry;
133  PVOID Context;
135 
136  *NextCluster = 0;
137 
138  Offset.QuadPart = 0;
139  _SEH2_TRY
140  {
141  CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector, MAP_WAIT, &Context, &BaseAddress);
142  }
144  {
146  }
147  _SEH2_END;
148 
149  CBlock = (PUSHORT)((char*)BaseAddress + (CurrentCluster * 12) / 8);
150  if ((CurrentCluster % 2) == 0)
151  {
152  Entry = *CBlock & 0x0fff;
153  }
154  else
155  {
156  Entry = *CBlock >> 4;
157  }
158 
159 // DPRINT("Entry %x\n",Entry);
160  if (Entry >= 0xff8 && Entry <= 0xfff)
161  Entry = 0xffffffff;
162 
163 // DPRINT("Returning %x\n",Entry);
164  ASSERT(Entry != 0);
165  *NextCluster = Entry;
167 // return Entry == 0xffffffff ? STATUS_END_OF_FILE : STATUS_SUCCESS;
168  return STATUS_SUCCESS;
169 }
170 
171 /*
172  * FUNCTION: Finds the first available cluster in a FAT16 table
173  */
174 NTSTATUS
176  PDEVICE_EXTENSION DeviceExt,
177  PULONG Cluster)
178 {
179  ULONG FatLength;
180  ULONG StartCluster;
181  ULONG i, j;
184  PVOID Context = 0;
186  PUSHORT Block;
187  PUSHORT BlockEnd;
188 
189  ChunkSize = CACHEPAGESIZE(DeviceExt);
190  FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2);
191  *Cluster = 0;
192  StartCluster = DeviceExt->LastAvailableCluster;
193 
194  for (j = 0; j < 2; j++)
195  {
196  for (i = StartCluster; i < FatLength;)
197  {
198  Offset.QuadPart = ROUND_DOWN(i * 2, ChunkSize);
199  _SEH2_TRY
200  {
201  CcPinRead(DeviceExt->FATFileObject, &Offset, ChunkSize, PIN_WAIT, &Context, &BaseAddress);
202  }
204  {
205  DPRINT1("CcPinRead(Offset %x, Length %u) failed\n", (ULONG)Offset.QuadPart, ChunkSize);
207  }
208  _SEH2_END;
209 
210  Block = (PUSHORT)((ULONG_PTR)BaseAddress + (i * 2) % ChunkSize);
211  BlockEnd = (PUSHORT)((ULONG_PTR)BaseAddress + ChunkSize);
212 
213  /* Now process the whole block */
214  while (Block < BlockEnd && i < FatLength)
215  {
216  if (*Block == 0)
217  {
218  DPRINT("Found available cluster 0x%x\n", i);
219  DeviceExt->LastAvailableCluster = *Cluster = i;
220  *Block = 0xffff;
223  if (DeviceExt->AvailableClustersValid)
224  InterlockedDecrement((PLONG)&DeviceExt->AvailableClusters);
225  return STATUS_SUCCESS;
226  }
227 
228  Block++;
229  i++;
230  }
231 
233  }
234 
235  FatLength = StartCluster;
236  StartCluster = 2;
237  }
238 
239  return STATUS_DISK_FULL;
240 }
241 
242 /*
243  * FUNCTION: Finds the first available cluster in a FAT12 table
244  */
245 NTSTATUS
247  PDEVICE_EXTENSION DeviceExt,
248  PULONG Cluster)
249 {
250  ULONG FatLength;
251  ULONG StartCluster;
252  ULONG Entry;
253  PUSHORT CBlock;
254  ULONG i, j;
256  PVOID Context;
258 
259  FatLength = DeviceExt->FatInfo.NumberOfClusters + 2;
260  *Cluster = 0;
261  StartCluster = DeviceExt->LastAvailableCluster;
262  Offset.QuadPart = 0;
263  _SEH2_TRY
264  {
265  CcPinRead(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector, PIN_WAIT, &Context, &BaseAddress);
266  }
268  {
269  DPRINT1("CcPinRead(Offset %x, Length %u) failed\n", (ULONG)Offset.QuadPart, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector);
271  }
272  _SEH2_END;
273 
274  for (j = 0; j < 2; j++)
275  {
276  for (i = StartCluster; i < FatLength; i++)
277  {
278  CBlock = (PUSHORT)((char*)BaseAddress + (i * 12) / 8);
279  if ((i % 2) == 0)
280  {
281  Entry = *CBlock & 0xfff;
282  }
283  else
284  {
285  Entry = *CBlock >> 4;
286  }
287 
288  if (Entry == 0)
289  {
290  DPRINT("Found available cluster 0x%x\n", i);
291  DeviceExt->LastAvailableCluster = *Cluster = i;
292  if ((i % 2) == 0)
293  *CBlock = (*CBlock & 0xf000) | 0xfff;
294  else
295  *CBlock = (*CBlock & 0xf) | 0xfff0;
298  if (DeviceExt->AvailableClustersValid)
299  InterlockedDecrement((PLONG)&DeviceExt->AvailableClusters);
300  return STATUS_SUCCESS;
301  }
302  }
303  FatLength = StartCluster;
304  StartCluster = 2;
305  }
307  return STATUS_DISK_FULL;
308 }
309 
310 /*
311  * FUNCTION: Finds the first available cluster in a FAT32 table
312  */
313 NTSTATUS
315  PDEVICE_EXTENSION DeviceExt,
316  PULONG Cluster)
317 {
318  ULONG FatLength;
319  ULONG StartCluster;
320  ULONG i, j;
323  PVOID Context;
325  PULONG Block;
326  PULONG BlockEnd;
327 
328  ChunkSize = CACHEPAGESIZE(DeviceExt);
329  FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2);
330  *Cluster = 0;
331  StartCluster = DeviceExt->LastAvailableCluster;
332 
333  for (j = 0; j < 2; j++)
334  {
335  for (i = StartCluster; i < FatLength;)
336  {
337  Offset.QuadPart = ROUND_DOWN(i * 4, ChunkSize);
338  _SEH2_TRY
339  {
340  CcPinRead(DeviceExt->FATFileObject, &Offset, ChunkSize, PIN_WAIT, &Context, &BaseAddress);
341  }
343  {
344  DPRINT1("CcPinRead(Offset %x, Length %u) failed\n", (ULONG)Offset.QuadPart, ChunkSize);
346  }
347  _SEH2_END;
348  Block = (PULONG)((ULONG_PTR)BaseAddress + (i * 4) % ChunkSize);
349  BlockEnd = (PULONG)((ULONG_PTR)BaseAddress + ChunkSize);
350 
351  /* Now process the whole block */
352  while (Block < BlockEnd && i < FatLength)
353  {
354  if ((*Block & 0x0fffffff) == 0)
355  {
356  DPRINT("Found available cluster 0x%x\n", i);
357  DeviceExt->LastAvailableCluster = *Cluster = i;
358  *Block = 0x0fffffff;
361  if (DeviceExt->AvailableClustersValid)
362  InterlockedDecrement((PLONG)&DeviceExt->AvailableClusters);
363  return STATUS_SUCCESS;
364  }
365 
366  Block++;
367  i++;
368  }
369 
371  }
372  FatLength = StartCluster;
373  StartCluster = 2;
374  }
375  return STATUS_DISK_FULL;
376 }
377 
378 /*
379  * FUNCTION: Counts free cluster in a FAT12 table
380  */
381 static
382 NTSTATUS
384  PDEVICE_EXTENSION DeviceExt)
385 {
386  ULONG Entry;
388  ULONG ulCount = 0;
389  ULONG i;
390  ULONG numberofclusters;
392  PVOID Context;
393  PUSHORT CBlock;
394 
395  Offset.QuadPart = 0;
396  _SEH2_TRY
397  {
398  CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector, MAP_WAIT, &Context, &BaseAddress);
399  }
401  {
403  }
404  _SEH2_END;
405 
406  numberofclusters = DeviceExt->FatInfo.NumberOfClusters + 2;
407 
408  for (i = 2; i < numberofclusters; i++)
409  {
410  CBlock = (PUSHORT)((char*)BaseAddress + (i * 12) / 8);
411  if ((i % 2) == 0)
412  {
413  Entry = *CBlock & 0x0fff;
414  }
415  else
416  {
417  Entry = *CBlock >> 4;
418  }
419 
420  if (Entry == 0)
421  ulCount++;
422  }
423 
425  DeviceExt->AvailableClusters = ulCount;
426  DeviceExt->AvailableClustersValid = TRUE;
427 
428  return STATUS_SUCCESS;
429 }
430 
431 
432 /*
433  * FUNCTION: Counts free clusters in a FAT16 table
434  */
435 static
436 NTSTATUS
438  PDEVICE_EXTENSION DeviceExt)
439 {
440  PUSHORT Block;
441  PUSHORT BlockEnd;
443  ULONG ulCount = 0;
444  ULONG i;
446  PVOID Context = NULL;
448  ULONG FatLength;
449 
450  ChunkSize = CACHEPAGESIZE(DeviceExt);
451  FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2);
452 
453  for (i = 2; i < FatLength; )
454  {
455  Offset.QuadPart = ROUND_DOWN(i * 2, ChunkSize);
456  _SEH2_TRY
457  {
458  CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, MAP_WAIT, &Context, &BaseAddress);
459  }
461  {
463  }
464  _SEH2_END;
465  Block = (PUSHORT)((ULONG_PTR)BaseAddress + (i * 2) % ChunkSize);
466  BlockEnd = (PUSHORT)((ULONG_PTR)BaseAddress + ChunkSize);
467 
468  /* Now process the whole block */
469  while (Block < BlockEnd && i < FatLength)
470  {
471  if (*Block == 0)
472  ulCount++;
473  Block++;
474  i++;
475  }
476 
478  }
479 
480  DeviceExt->AvailableClusters = ulCount;
481  DeviceExt->AvailableClustersValid = TRUE;
482 
483  return STATUS_SUCCESS;
484 }
485 
486 
487 /*
488  * FUNCTION: Counts free clusters in a FAT32 table
489  */
490 static
491 NTSTATUS
493  PDEVICE_EXTENSION DeviceExt)
494 {
495  PULONG Block;
496  PULONG BlockEnd;
498  ULONG ulCount = 0;
499  ULONG i;
501  PVOID Context = NULL;
503  ULONG FatLength;
504 
505  ChunkSize = CACHEPAGESIZE(DeviceExt);
506  FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2);
507 
508  for (i = 2; i < FatLength; )
509  {
510  Offset.QuadPart = ROUND_DOWN(i * 4, ChunkSize);
511  _SEH2_TRY
512  {
513  CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, MAP_WAIT, &Context, &BaseAddress);
514  }
516  {
517  DPRINT1("CcMapData(Offset %x, Length %u) failed\n", (ULONG)Offset.QuadPart, ChunkSize);
519  }
520  _SEH2_END;
521  Block = (PULONG)((ULONG_PTR)BaseAddress + (i * 4) % ChunkSize);
522  BlockEnd = (PULONG)((ULONG_PTR)BaseAddress + ChunkSize);
523 
524  /* Now process the whole block */
525  while (Block < BlockEnd && i < FatLength)
526  {
527  if ((*Block & 0x0fffffff) == 0)
528  ulCount++;
529  Block++;
530  i++;
531  }
532 
534  }
535 
536  DeviceExt->AvailableClusters = ulCount;
537  DeviceExt->AvailableClustersValid = TRUE;
538 
539  return STATUS_SUCCESS;
540 }
541 
542 NTSTATUS
544  PDEVICE_EXTENSION DeviceExt,
545  PLARGE_INTEGER Clusters)
546 {
548  ExAcquireResourceExclusiveLite (&DeviceExt->FatResource, TRUE);
549  if (!DeviceExt->AvailableClustersValid)
550  {
551  if (DeviceExt->FatInfo.FatType == FAT12)
552  Status = FAT12CountAvailableClusters(DeviceExt);
553  else if (DeviceExt->FatInfo.FatType == FAT16 || DeviceExt->FatInfo.FatType == FATX16)
554  Status = FAT16CountAvailableClusters(DeviceExt);
555  else
556  Status = FAT32CountAvailableClusters(DeviceExt);
557  }
558  if (Clusters != NULL)
559  {
560  Clusters->QuadPart = DeviceExt->AvailableClusters;
561  }
562  ExReleaseResourceLite (&DeviceExt->FatResource);
563 
564  return Status;
565 }
566 
567 
568 /*
569  * FUNCTION: Writes a cluster to the FAT12 physical and in-memory tables
570  */
571 NTSTATUS
573  PDEVICE_EXTENSION DeviceExt,
574  ULONG ClusterToWrite,
575  ULONG NewValue,
576  PULONG OldValue)
577 {
578  ULONG FATOffset;
579  PUCHAR CBlock;
581  PVOID Context;
583 
584  Offset.QuadPart = 0;
585  _SEH2_TRY
586  {
587  CcPinRead(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector, PIN_WAIT, &Context, &BaseAddress);
588  }
590  {
592  }
593  _SEH2_END;
594  CBlock = (PUCHAR)BaseAddress;
595 
596  FATOffset = (ClusterToWrite * 12) / 8;
597  DPRINT("Writing 0x%x for 0x%x at 0x%x\n",
598  NewValue, ClusterToWrite, FATOffset);
599  if ((ClusterToWrite % 2) == 0)
600  {
601  *OldValue = CBlock[FATOffset] + ((CBlock[FATOffset + 1] & 0x0f) << 8);
602  CBlock[FATOffset] = (UCHAR)NewValue;
603  CBlock[FATOffset + 1] &= 0xf0;
604  CBlock[FATOffset + 1] |= (NewValue & 0xf00) >> 8;
605  }
606  else
607  {
608  *OldValue = (CBlock[FATOffset] >> 4) + (CBlock[FATOffset + 1] << 4);
609  CBlock[FATOffset] &= 0x0f;
610  CBlock[FATOffset] |= (NewValue & 0xf) << 4;
611  CBlock[FATOffset + 1] = (UCHAR)(NewValue >> 4);
612  }
613  /* Write the changed FAT sector(s) to disk */
616  return STATUS_SUCCESS;
617 }
618 
619 /*
620  * FUNCTION: Writes a cluster to the FAT16 physical and in-memory tables
621  */
622 NTSTATUS
624  PDEVICE_EXTENSION DeviceExt,
625  ULONG ClusterToWrite,
626  ULONG NewValue,
627  PULONG OldValue)
628 {
630  ULONG FATOffset;
632  PVOID Context;
634  PUSHORT Cluster;
635 
636  ChunkSize = CACHEPAGESIZE(DeviceExt);
637  FATOffset = ClusterToWrite * 2;
638  Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize);
639  _SEH2_TRY
640  {
641  CcPinRead(DeviceExt->FATFileObject, &Offset, ChunkSize, PIN_WAIT, &Context, &BaseAddress);
642  }
644  {
646  }
647  _SEH2_END;
648 
649  DPRINT("Writing 0x%x for offset 0x%x 0x%x\n", NewValue, FATOffset,
650  ClusterToWrite);
651  Cluster = ((PUSHORT)((char*)BaseAddress + (FATOffset % ChunkSize)));
652  *OldValue = *Cluster;
653  *Cluster = (USHORT)NewValue;
656  return STATUS_SUCCESS;
657 }
658 
659 /*
660  * FUNCTION: Writes a cluster to the FAT32 physical tables
661  */
662 NTSTATUS
664  PDEVICE_EXTENSION DeviceExt,
665  ULONG ClusterToWrite,
666  ULONG NewValue,
667  PULONG OldValue)
668 {
670  ULONG FATOffset;
672  PVOID Context;
674  PULONG Cluster;
675 
676  ChunkSize = CACHEPAGESIZE(DeviceExt);
677 
678  FATOffset = (ClusterToWrite * 4);
679  Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize);
680  _SEH2_TRY
681  {
682  CcPinRead(DeviceExt->FATFileObject, &Offset, ChunkSize, PIN_WAIT, &Context, &BaseAddress);
683  }
685  {
687  }
688  _SEH2_END;
689 
690  DPRINT("Writing 0x%x for offset 0x%x 0x%x\n", NewValue, FATOffset,
691  ClusterToWrite);
692  Cluster = ((PULONG)((char*)BaseAddress + (FATOffset % ChunkSize)));
693  *OldValue = *Cluster & 0x0fffffff;
694  *Cluster = (*Cluster & 0xf0000000) | (NewValue & 0x0fffffff);
695 
698 
699  return STATUS_SUCCESS;
700 }
701 
702 
703 /*
704  * FUNCTION: Write a changed FAT entry
705  */
706 NTSTATUS
708  PDEVICE_EXTENSION DeviceExt,
709  ULONG ClusterToWrite,
710  ULONG NewValue)
711 {
713  ULONG OldValue;
714 
715  ExAcquireResourceExclusiveLite (&DeviceExt->FatResource, TRUE);
716  Status = DeviceExt->WriteCluster(DeviceExt, ClusterToWrite, NewValue, &OldValue);
717  if (DeviceExt->AvailableClustersValid)
718  {
719  if (OldValue && NewValue == 0)
720  InterlockedIncrement((PLONG)&DeviceExt->AvailableClusters);
721  else if (OldValue == 0 && NewValue)
722  InterlockedDecrement((PLONG)&DeviceExt->AvailableClusters);
723  }
724  ExReleaseResourceLite(&DeviceExt->FatResource);
725  return Status;
726 }
727 
728 /*
729  * FUNCTION: Converts the cluster number to a sector number for this physical
730  * device
731  */
732 ULONGLONG
734  PDEVICE_EXTENSION DeviceExt,
735  ULONG Cluster)
736 {
737  return DeviceExt->FatInfo.dataStart +
738  ((ULONGLONG)(Cluster - 2) * DeviceExt->FatInfo.SectorsPerCluster);
739 
740 }
741 
742 /*
743  * FUNCTION: Retrieve the next cluster depending on the FAT type
744  */
745 NTSTATUS
747  PDEVICE_EXTENSION DeviceExt,
748  ULONG CurrentCluster,
750 {
752 
753  DPRINT("GetNextCluster(DeviceExt %p, CurrentCluster %x)\n",
754  DeviceExt, CurrentCluster);
755 
756  if (CurrentCluster == 0)
757  {
758  DPRINT1("WARNING: File system corruption detected. You may need to run a disk repair utility.\n");
760  ASSERT(CurrentCluster != 0);
762  }
763 
764  ExAcquireResourceSharedLite(&DeviceExt->FatResource, TRUE);
765  Status = DeviceExt->GetNextCluster(DeviceExt, CurrentCluster, NextCluster);
766  ExReleaseResourceLite(&DeviceExt->FatResource);
767 
768  return Status;
769 }
770 
771 /*
772  * FUNCTION: Retrieve the next cluster depending on the FAT type
773  */
774 NTSTATUS
776  PDEVICE_EXTENSION DeviceExt,
777  ULONG CurrentCluster,
779 {
780  ULONG NewCluster;
782 
783  DPRINT("GetNextClusterExtend(DeviceExt %p, CurrentCluster %x)\n",
784  DeviceExt, CurrentCluster);
785 
786  ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);
787  /*
788  * If the file hasn't any clusters allocated then we need special
789  * handling
790  */
791  if (CurrentCluster == 0)
792  {
793  Status = DeviceExt->FindAndMarkAvailableCluster(DeviceExt, &NewCluster);
794  if (!NT_SUCCESS(Status))
795  {
796  ExReleaseResourceLite(&DeviceExt->FatResource);
797  return Status;
798  }
799 
800  *NextCluster = NewCluster;
801  ExReleaseResourceLite(&DeviceExt->FatResource);
802  return STATUS_SUCCESS;
803  }
804 
805  Status = DeviceExt->GetNextCluster(DeviceExt, CurrentCluster, NextCluster);
806 
807  if ((*NextCluster) == 0xFFFFFFFF)
808  {
809  /* We are after last existing cluster, we must add one to file */
810  /* Firstly, find the next available open allocation unit and
811  mark it as end of file */
812  Status = DeviceExt->FindAndMarkAvailableCluster(DeviceExt, &NewCluster);
813  if (!NT_SUCCESS(Status))
814  {
815  ExReleaseResourceLite(&DeviceExt->FatResource);
816  return Status;
817  }
818 
819  /* Now, write the AU of the LastCluster with the value of the newly
820  found AU */
821  WriteCluster(DeviceExt, CurrentCluster, NewCluster);
822  *NextCluster = NewCluster;
823  }
824 
825  ExReleaseResourceLite(&DeviceExt->FatResource);
826  return Status;
827 }
828 
829 /*
830  * FUNCTION: Retrieve the dirty status
831  */
832 NTSTATUS
834  PDEVICE_EXTENSION DeviceExt,
835  PBOOLEAN DirtyStatus)
836 {
838 
839  DPRINT("GetDirtyStatus(DeviceExt %p)\n", DeviceExt);
840 
841  /* FAT12 has no dirty bit */
842  if (DeviceExt->FatInfo.FatType == FAT12)
843  {
844  *DirtyStatus = FALSE;
845  return STATUS_SUCCESS;
846  }
847 
848  /* Not really in the FAT, but share the lock because
849  * we're really low-level and shouldn't happent that often
850  * And call the appropriate function
851  */
852  ExAcquireResourceSharedLite(&DeviceExt->FatResource, TRUE);
853  Status = DeviceExt->GetDirtyStatus(DeviceExt, DirtyStatus);
854  ExReleaseResourceLite(&DeviceExt->FatResource);
855 
856  return Status;
857 }
858 
859 NTSTATUS
861  PDEVICE_EXTENSION DeviceExt,
862  PBOOLEAN DirtyStatus)
863 {
865  ULONG Length;
866 #ifdef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
868 #else
869  PVOID Context;
870 #endif
871  struct _BootSector * Sector;
872 
873  /* We'll read the bootsector at 0 */
874  Offset.QuadPart = 0;
875  Length = DeviceExt->FatInfo.BytesPerSector;
876 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
877  /* Go through Cc for this */
878  _SEH2_TRY
879  {
880  CcPinRead(DeviceExt->VolumeFcb->FileObject, &Offset, Length, PIN_WAIT, &Context, (PVOID *)&Sector);
881  }
883  {
885  }
886  _SEH2_END;
887 #else
888  /* No Cc, do it the old way:
889  * - Allocate a big enough buffer
890  * - And read the disk
891  */
893  if (Sector == NULL)
894  {
895  *DirtyStatus = TRUE;
897  }
898 
899  Status = VfatReadDisk(DeviceExt->StorageDevice, &Offset, Length, (PUCHAR)Sector, FALSE);
900  if (!NT_SUCCESS(Status))
901  {
902  *DirtyStatus = TRUE;
903  ExFreePoolWithTag(Sector, TAG_BUFFER);
904  return Status;
905  }
906 #endif
907 
908  /* Make sure we have a boot sector...
909  * FIXME: This check is a bit lame and should be improved
910  */
911  if (Sector->Signatur1 != 0xaa55)
912  {
913  /* Set we are dirty so that we don't attempt anything */
914  *DirtyStatus = TRUE;
915 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
917 #else
918  ExFreePoolWithTag(Sector, TAG_BUFFER);
919 #endif
921  }
922 
923  /* Return the status of the dirty bit */
924  if (Sector->Res1 & FAT_DIRTY_BIT)
925  *DirtyStatus = TRUE;
926  else
927  *DirtyStatus = FALSE;
928 
929 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
931 #else
932  ExFreePoolWithTag(Sector, TAG_BUFFER);
933 #endif
934  return STATUS_SUCCESS;
935 }
936 
937 NTSTATUS
939  PDEVICE_EXTENSION DeviceExt,
940  PBOOLEAN DirtyStatus)
941 {
943  ULONG Length;
944 #ifdef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
946 #else
947  PVOID Context;
948 #endif
949  struct _BootSector32 * Sector;
950 
951  /* We'll read the bootsector at 0 */
952  Offset.QuadPart = 0;
953  Length = DeviceExt->FatInfo.BytesPerSector;
954 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
955  /* Go through Cc for this */
956  _SEH2_TRY
957  {
958  CcPinRead(DeviceExt->VolumeFcb->FileObject, &Offset, Length, PIN_WAIT, &Context, (PVOID *)&Sector);
959  }
961  {
963  }
964  _SEH2_END;
965 #else
966  /* No Cc, do it the old way:
967  * - Allocate a big enough buffer
968  * - And read the disk
969  */
971  if (Sector == NULL)
972  {
973  *DirtyStatus = TRUE;
975  }
976 
977  Status = VfatReadDisk(DeviceExt->StorageDevice, &Offset, Length, (PUCHAR)Sector, FALSE);
978  if (!NT_SUCCESS(Status))
979  {
980  *DirtyStatus = TRUE;
981  ExFreePoolWithTag(Sector, TAG_BUFFER);
982  return Status;
983  }
984 #endif
985 
986  /* Make sure we have a boot sector...
987  * FIXME: This check is a bit lame and should be improved
988  */
989  if (Sector->Signature1 != 0xaa55)
990  {
991  /* Set we are dirty so that we don't attempt anything */
992  *DirtyStatus = TRUE;
993 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
995 #else
996  ExFreePoolWithTag(Sector, TAG_BUFFER);
997 #endif
999  }
1000 
1001  /* Return the status of the dirty bit */
1002  if (Sector->Res4 & FAT_DIRTY_BIT)
1003  *DirtyStatus = TRUE;
1004  else
1005  *DirtyStatus = FALSE;
1006 
1007 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1009 #else
1010  ExFreePoolWithTag(Sector, TAG_BUFFER);
1011 #endif
1012  return STATUS_SUCCESS;
1013 }
1014 
1015 /*
1016  * FUNCTION: Set the dirty status
1017  */
1018 NTSTATUS
1020  PDEVICE_EXTENSION DeviceExt,
1021  BOOLEAN DirtyStatus)
1022 {
1023  NTSTATUS Status;
1024 
1025  DPRINT("SetDirtyStatus(DeviceExt %p, DirtyStatus %d)\n", DeviceExt, DirtyStatus);
1026 
1027  /* FAT12 has no dirty bit */
1028  if (DeviceExt->FatInfo.FatType == FAT12)
1029  {
1030  return STATUS_SUCCESS;
1031  }
1032 
1033  /* Not really in the FAT, but share the lock because
1034  * we're really low-level and shouldn't happent that often
1035  * And call the appropriate function
1036  * Acquire exclusive because we will modify ondisk value
1037  */
1038  ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);
1039  Status = DeviceExt->SetDirtyStatus(DeviceExt, DirtyStatus);
1040  ExReleaseResourceLite(&DeviceExt->FatResource);
1041 
1042  return Status;
1043 }
1044 
1045 NTSTATUS
1047  PDEVICE_EXTENSION DeviceExt,
1048  BOOLEAN DirtyStatus)
1049 {
1051  ULONG Length;
1052 #ifdef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1053  NTSTATUS Status;
1054 #else
1055  PVOID Context;
1056 #endif
1057  struct _BootSector * Sector;
1058 
1059  /* We'll read (and then write) the bootsector at 0 */
1060  Offset.QuadPart = 0;
1061  Length = DeviceExt->FatInfo.BytesPerSector;
1062 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1063  /* Go through Cc for this */
1064  _SEH2_TRY
1065  {
1066  CcPinRead(DeviceExt->VolumeFcb->FileObject, &Offset, Length, PIN_WAIT, &Context, (PVOID *)&Sector);
1067  }
1069  {
1071  }
1072  _SEH2_END;
1073 #else
1074  /* No Cc, do it the old way:
1075  * - Allocate a big enough buffer
1076  * - And read the disk
1077  */
1079  if (Sector == NULL)
1080  {
1082  }
1083 
1084  Status = VfatReadDisk(DeviceExt->StorageDevice, &Offset, Length, (PUCHAR)Sector, FALSE);
1085  if (!NT_SUCCESS(Status))
1086  {
1087  ExFreePoolWithTag(Sector, TAG_BUFFER);
1088  return Status;
1089  }
1090 #endif
1091 
1092  /* Make sure we have a boot sector...
1093  * FIXME: This check is a bit lame and should be improved
1094  */
1095  if (Sector->Signatur1 != 0xaa55)
1096  {
1097 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1099 #else
1100  ExFreePoolWithTag(Sector, TAG_BUFFER);
1101 #endif
1103  }
1104 
1105  /* Modify the dirty bit status according
1106  * to caller needs
1107  */
1108  if (!DirtyStatus)
1109  {
1110  Sector->Res1 &= ~FAT_DIRTY_BIT;
1111  }
1112  else
1113  {
1114  Sector->Res1 |= FAT_DIRTY_BIT;
1115  }
1116 
1117 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1118  /* Mark boot sector dirty so that it gets written to the disk */
1121  return STATUS_SUCCESS;
1122 #else
1123  /* Write back the boot sector to the disk */
1124  Status = VfatWriteDisk(DeviceExt->StorageDevice, &Offset, Length, (PUCHAR)Sector, FALSE);
1125  ExFreePoolWithTag(Sector, TAG_BUFFER);
1126  return Status;
1127 #endif
1128 }
1129 
1130 NTSTATUS
1132  PDEVICE_EXTENSION DeviceExt,
1133  BOOLEAN DirtyStatus)
1134 {
1136  ULONG Length;
1137 #ifdef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1138  NTSTATUS Status;
1139 #else
1140  PVOID Context;
1141 #endif
1142  struct _BootSector32 * Sector;
1143 
1144  /* We'll read (and then write) the bootsector at 0 */
1145  Offset.QuadPart = 0;
1146  Length = DeviceExt->FatInfo.BytesPerSector;
1147 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1148  /* Go through Cc for this */
1149  _SEH2_TRY
1150  {
1151  CcPinRead(DeviceExt->VolumeFcb->FileObject, &Offset, Length, PIN_WAIT, &Context, (PVOID *)&Sector);
1152  }
1154  {
1156  }
1157  _SEH2_END;
1158 #else
1159  /* No Cc, do it the old way:
1160  * - Allocate a big enough buffer
1161  * - And read the disk
1162  */
1164  if (Sector == NULL)
1165  {
1167  }
1168 
1169  Status = VfatReadDisk(DeviceExt->StorageDevice, &Offset, Length, (PUCHAR)Sector, FALSE);
1170  if (!NT_SUCCESS(Status))
1171  {
1172  ExFreePoolWithTag(Sector, TAG_BUFFER);
1173  return Status;
1174  }
1175 #endif
1176 
1177  /* Make sure we have a boot sector...
1178  * FIXME: This check is a bit lame and should be improved
1179  */
1180  if (Sector->Signature1 != 0xaa55)
1181  {
1182  ASSERT(FALSE);
1183 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1185 #else
1186  ExFreePoolWithTag(Sector, TAG_BUFFER);
1187 #endif
1189  }
1190 
1191  /* Modify the dirty bit status according
1192  * to caller needs
1193  */
1194  if (!DirtyStatus)
1195  {
1196  Sector->Res4 &= ~FAT_DIRTY_BIT;
1197  }
1198  else
1199  {
1200  Sector->Res4 |= FAT_DIRTY_BIT;
1201  }
1202 
1203 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1204  /* Mark boot sector dirty so that it gets written to the disk */
1207  return STATUS_SUCCESS;
1208 #else
1209  /* Write back the boot sector to the disk */
1210  Status = VfatWriteDisk(DeviceExt->StorageDevice, &Offset, Length, (PUCHAR)Sector, FALSE);
1211  ExFreePoolWithTag(Sector, TAG_BUFFER);
1212  return Status;
1213 #endif
1214 }
1215 
1216 NTSTATUS
1218  PDEVICE_EXTENSION DeviceExt)
1219 {
1221  ULONG Length;
1222 #ifdef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1223  NTSTATUS Status;
1224 #else
1225  PVOID Context;
1226 #endif
1227  struct _FsInfoSector * Sector;
1228 
1229  if (!DeviceExt->AvailableClustersValid)
1230  {
1231  return STATUS_INVALID_PARAMETER;
1232  }
1233 
1234  /* We'll read (and then write) the fsinfo sector */
1235  Offset.QuadPart = DeviceExt->FatInfo.FSInfoSector * DeviceExt->FatInfo.BytesPerSector;
1236  Length = DeviceExt->FatInfo.BytesPerSector;
1237 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1238  /* Go through Cc for this */
1239  _SEH2_TRY
1240  {
1241  CcPinRead(DeviceExt->VolumeFcb->FileObject, &Offset, Length, PIN_WAIT, &Context, (PVOID *)&Sector);
1242  }
1244  {
1246  }
1247  _SEH2_END;
1248 #else
1249  /* No Cc, do it the old way:
1250  * - Allocate a big enough buffer
1251  * - And read the disk
1252  */
1254  if (Sector == NULL)
1255  {
1257  }
1258 
1259  Status = VfatReadDisk(DeviceExt->StorageDevice, &Offset, Length, (PUCHAR)Sector, FALSE);
1260  if (!NT_SUCCESS(Status))
1261  {
1262  ExFreePoolWithTag(Sector, TAG_BUFFER);
1263  return Status;
1264  }
1265 #endif
1266 
1267  /* Make sure we have a FSINFO sector */
1268  if (Sector->ExtBootSignature2 != 0x41615252 ||
1269  Sector->FSINFOSignature != 0x61417272 ||
1270  Sector->Signatur2 != 0xaa550000)
1271  {
1272  ASSERT(FALSE);
1273 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1275 #else
1276  ExFreePoolWithTag(Sector, TAG_BUFFER);
1277 #endif
1279  }
1280 
1281  /* Update the free clusters count */
1282  Sector->FreeCluster = InterlockedCompareExchange((PLONG)&DeviceExt->AvailableClusters, 0, 0);
1283 
1284 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1285  /* Mark FSINFO sector dirty so that it gets written to the disk */
1288  return STATUS_SUCCESS;
1289 #else
1290  /* Write back the FSINFO sector to the disk */
1291  Status = VfatWriteDisk(DeviceExt->StorageDevice, &Offset, Length, (PUCHAR)Sector, FALSE);
1292  ExFreePoolWithTag(Sector, TAG_BUFFER);
1293  return Status;
1294 #endif
1295 }
1296 
1297 /* EOF */
NTSTATUS FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, ULONG NewValue, PULONG OldValue)
Definition: fat.c:572
#define FAT12
Definition: fat.h:167
NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, PULONG CurrentCluster, BOOLEAN Extend)
Definition: rw.c:40
NTSTATUS CountAvailableClusters(PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER Clusters)
Definition: fat.c:543
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
struct _Entry Entry
Definition: kefuncs.h:627
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
NTSTATUS FAT16GetDirtyStatus(PDEVICE_EXTENSION DeviceExt, PBOOLEAN DirtyStatus)
Definition: fat.c:860
VOID NTAPI CcSetDirtyPinnedData(IN PVOID BcbVoid, IN OPTIONAL PLARGE_INTEGER Lsn)
Definition: cachesub.c:121
NTSTATUS FAT32UpdateFreeClustersCount(PDEVICE_EXTENSION DeviceExt)
Definition: fat.c:1217
unsigned char * PUCHAR
Definition: retypes.h:3
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS FAT32GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:30
VOID NTAPI CcUnpinData(IN PVOID Bcb)
Definition: pinsup.c:955
#define MAP_WAIT
#define InterlockedCompareExchange
Definition: interlocked.h:104
#define PIN_WAIT
NTSTATUS FAT32SetDirtyStatus(PDEVICE_EXTENSION DeviceExt, BOOLEAN DirtyStatus)
Definition: fat.c:1131
NTSTATUS FAT32FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
Definition: fat.c:314
_SEH2_TRY
Definition: create.c:4226
uint32_t ULONG_PTR
Definition: typedefs.h:65
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define STATUS_FILE_CORRUPT_ERROR
Definition: udferr_usr.h:168
NTSTATUS GetDirtyStatus(PDEVICE_EXTENSION DeviceExt, PBOOLEAN DirtyStatus)
Definition: fat.c:833
#define TAG_BUFFER
Definition: vfat.h:551
#define FALSE
Definition: types.h:117
_Inout_ PUCHAR _In_ PUCHAR _Out_ PUCHAR _Out_ PULONG ChunkSize
Definition: rtlfuncs.h:2276
static NTSTATUS FAT16CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
Definition: fat.c:437
NTSTATUS FAT12FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
Definition: fat.c:246
unsigned char BOOLEAN
NTSTATUS FAT12GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:125
NTSTATUS FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, ULONG NewValue, PULONG OldValue)
Definition: fat.c:663
NTSTATUS FAT16FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
Definition: fat.c:175
NTSTATUS WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, ULONG NewValue)
Definition: fat.c:707
NTSTATUS VfatReadDisk(IN PDEVICE_OBJECT pDeviceObject, IN PLARGE_INTEGER ReadOffset, IN ULONG ReadLength, IN OUT PUCHAR Buffer, IN BOOLEAN Override)
Definition: blockdev.c:72
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 GLint GLint j
Definition: glfuncs.h:250
Status
Definition: gdiplustypes.h:24
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
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
NTSTATUS GetNextClusterExtend(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:775
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
uint64_t ULONGLONG
Definition: typedefs.h:67
static NTSTATUS FAT12CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
Definition: fat.c:383
static NTSTATUS FAT32CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
Definition: fat.c:492
NTSTATUS VfatWriteDisk(IN PDEVICE_OBJECT pDeviceObject, IN PLARGE_INTEGER WriteOffset, IN ULONG WriteLength, IN OUT PUCHAR Buffer, IN BOOLEAN Override)
Definition: blockdev.c:255
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
BOOLEAN NTAPI CcPinRead(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, OUT PVOID *Bcb, OUT PVOID *Buffer)
Definition: pinsup.c:802
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
unsigned char UCHAR
Definition: xmlstorage.h:181
char * PBOOLEAN
Definition: retypes.h:11
#define InterlockedDecrement
Definition: armddk.h:52
#define FAT16
Definition: fat.h:168
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define VFAT_BREAK_ON_CORRUPTION
Definition: vfat.h:407
PVFAT_GLOBAL_DATA VfatGlobalData
Definition: iface.c:36
#define ROUND_DOWN(n, align)
Definition: eventvwr.h:30
NTSTATUS FAT32GetDirtyStatus(PDEVICE_EXTENSION DeviceExt, PBOOLEAN DirtyStatus)
Definition: fat.c:938
NTSTATUS GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:746
_SEH2_END
Definition: create.c:4400
#define InterlockedIncrement
Definition: armddk.h:53
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
unsigned short USHORT
Definition: pedump.c:61
#define FAT_DIRTY_BIT
Definition: vfat.h:85
#define FATX16
Definition: fat.h:170
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
ULONG Flags
Definition: vfat.h:413
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
#define DPRINT1
Definition: precomp.h:8
#define CACHEPAGESIZE(pDeviceExt)
Definition: fat.c:20
NTSTATUS FAT16GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:79
struct tagContext Context
Definition: acpixf.h:1034
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155
#define STATUS_DISK_CORRUPT_ERROR
Definition: udferr_usr.h:147
NTSTATUS FAT16SetDirtyStatus(PDEVICE_EXTENSION DeviceExt, BOOLEAN DirtyStatus)
Definition: fat.c:1046
unsigned int ULONG
Definition: retypes.h:1
NTSTATUS FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, ULONG NewValue, PULONG OldValue)
Definition: fat.c:623
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define STATUS_SUCCESS
Definition: shellext.h:65
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
#define DPRINT
Definition: sndvol32.h:71
NTSTATUS SetDirtyStatus(PDEVICE_EXTENSION DeviceExt, BOOLEAN DirtyStatus)
Definition: fat.c:1019
signed int * PLONG
Definition: retypes.h:5
ULONGLONG ClusterToSector(PDEVICE_EXTENSION DeviceExt, ULONG Cluster)
Definition: fat.c:733
unsigned short * PUSHORT
Definition: retypes.h:2
base of all file and directory entries
Definition: entries.h:82
LONGLONG QuadPart
Definition: typedefs.h:114
#define NT_ASSERT
Definition: rtlfuncs.h:3312