ReactOS  0.4.14-dev-52-g6116262
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;
41 
42  ChunkSize = CACHEPAGESIZE(DeviceExt);
43  FATOffset = CurrentCluster * sizeof(ULONG);
44  Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize);
45  _SEH2_TRY
46  {
47  CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, MAP_WAIT, &Context, &BaseAddress);
48  }
50  {
52  }
53  _SEH2_END;
54 
55  CurrentCluster = (*(PULONG)((char*)BaseAddress + (FATOffset % ChunkSize))) & 0x0fffffff;
56  if (CurrentCluster >= 0xffffff8 && CurrentCluster <= 0xfffffff)
57  CurrentCluster = 0xffffffff;
58 
59  if (CurrentCluster == 0)
60  {
61  DPRINT1("WARNING: File system corruption detected. You may need to run a disk repair utility.\n");
64  ASSERT(CurrentCluster != 0);
65  }
67  *NextCluster = CurrentCluster;
68  return Status;
69 }
70 
71 /*
72  * FUNCTION: Retrieve the next FAT16 cluster from the FAT table
73  */
76  PDEVICE_EXTENSION DeviceExt,
77  ULONG CurrentCluster,
79 {
82  ULONG FATOffset;
84  PVOID Context;
86 
87  ChunkSize = CACHEPAGESIZE(DeviceExt);
88  FATOffset = CurrentCluster * 2;
89  Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize);
90  _SEH2_TRY
91  {
92  CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, MAP_WAIT, &Context, &BaseAddress);
93  }
95  {
97  }
98  _SEH2_END;
99 
100  CurrentCluster = *((PUSHORT)((char*)BaseAddress + (FATOffset % ChunkSize)));
101  if (CurrentCluster >= 0xfff8 && CurrentCluster <= 0xffff)
102  CurrentCluster = 0xffffffff;
103 
104  if (CurrentCluster == 0)
105  {
106  DPRINT1("WARNING: File system corruption detected. You may need to run a disk repair utility.\n");
109  ASSERT(CurrentCluster != 0);
110  }
111 
113  *NextCluster = CurrentCluster;
114  return Status;
115 }
116 
117 /*
118  * FUNCTION: Retrieve the next FAT12 cluster from the FAT table
119  */
120 NTSTATUS
122  PDEVICE_EXTENSION DeviceExt,
123  ULONG CurrentCluster,
125 {
126  PUSHORT CBlock;
127  ULONG Entry;
129  PVOID Context;
131 
132  *NextCluster = 0;
133 
134  Offset.QuadPart = 0;
135  _SEH2_TRY
136  {
137  CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector, MAP_WAIT, &Context, &BaseAddress);
138  }
140  {
142  }
143  _SEH2_END;
144 
145  CBlock = (PUSHORT)((char*)BaseAddress + (CurrentCluster * 12) / 8);
146  if ((CurrentCluster % 2) == 0)
147  {
148  Entry = *CBlock & 0x0fff;
149  }
150  else
151  {
152  Entry = *CBlock >> 4;
153  }
154 
155 // DPRINT("Entry %x\n",Entry);
156  if (Entry >= 0xff8 && Entry <= 0xfff)
157  Entry = 0xffffffff;
158 
159 // DPRINT("Returning %x\n",Entry);
160  ASSERT(Entry != 0);
161  *NextCluster = Entry;
163 // return Entry == 0xffffffff ? STATUS_END_OF_FILE : STATUS_SUCCESS;
164  return STATUS_SUCCESS;
165 }
166 
167 /*
168  * FUNCTION: Finds the first available cluster in a FAT16 table
169  */
170 NTSTATUS
172  PDEVICE_EXTENSION DeviceExt,
173  PULONG Cluster)
174 {
175  ULONG FatLength;
176  ULONG StartCluster;
177  ULONG i, j;
180  PVOID Context = 0;
182  PUSHORT Block;
183  PUSHORT BlockEnd;
184 
185  ChunkSize = CACHEPAGESIZE(DeviceExt);
186  FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2);
187  *Cluster = 0;
188  StartCluster = DeviceExt->LastAvailableCluster;
189 
190  for (j = 0; j < 2; j++)
191  {
192  for (i = StartCluster; i < FatLength;)
193  {
194  Offset.QuadPart = ROUND_DOWN(i * 2, ChunkSize);
195  _SEH2_TRY
196  {
197  CcPinRead(DeviceExt->FATFileObject, &Offset, ChunkSize, PIN_WAIT, &Context, &BaseAddress);
198  }
200  {
201  DPRINT1("CcPinRead(Offset %x, Length %u) failed\n", (ULONG)Offset.QuadPart, ChunkSize);
203  }
204  _SEH2_END;
205 
206  Block = (PUSHORT)((ULONG_PTR)BaseAddress + (i * 2) % ChunkSize);
207  BlockEnd = (PUSHORT)((ULONG_PTR)BaseAddress + ChunkSize);
208 
209  /* Now process the whole block */
210  while (Block < BlockEnd && i < FatLength)
211  {
212  if (*Block == 0)
213  {
214  DPRINT("Found available cluster 0x%x\n", i);
215  DeviceExt->LastAvailableCluster = *Cluster = i;
216  *Block = 0xffff;
219  if (DeviceExt->AvailableClustersValid)
220  InterlockedDecrement((PLONG)&DeviceExt->AvailableClusters);
221  return STATUS_SUCCESS;
222  }
223 
224  Block++;
225  i++;
226  }
227 
229  }
230 
231  FatLength = StartCluster;
232  StartCluster = 2;
233  }
234 
235  return STATUS_DISK_FULL;
236 }
237 
238 /*
239  * FUNCTION: Finds the first available cluster in a FAT12 table
240  */
241 NTSTATUS
243  PDEVICE_EXTENSION DeviceExt,
244  PULONG Cluster)
245 {
246  ULONG FatLength;
247  ULONG StartCluster;
248  ULONG Entry;
249  PUSHORT CBlock;
250  ULONG i, j;
252  PVOID Context;
254 
255  FatLength = DeviceExt->FatInfo.NumberOfClusters + 2;
256  *Cluster = 0;
257  StartCluster = DeviceExt->LastAvailableCluster;
258  Offset.QuadPart = 0;
259  _SEH2_TRY
260  {
261  CcPinRead(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector, PIN_WAIT, &Context, &BaseAddress);
262  }
264  {
265  DPRINT1("CcPinRead(Offset %x, Length %u) failed\n", (ULONG)Offset.QuadPart, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector);
267  }
268  _SEH2_END;
269 
270  for (j = 0; j < 2; j++)
271  {
272  for (i = StartCluster; i < FatLength; i++)
273  {
274  CBlock = (PUSHORT)((char*)BaseAddress + (i * 12) / 8);
275  if ((i % 2) == 0)
276  {
277  Entry = *CBlock & 0xfff;
278  }
279  else
280  {
281  Entry = *CBlock >> 4;
282  }
283 
284  if (Entry == 0)
285  {
286  DPRINT("Found available cluster 0x%x\n", i);
287  DeviceExt->LastAvailableCluster = *Cluster = i;
288  if ((i % 2) == 0)
289  *CBlock = (*CBlock & 0xf000) | 0xfff;
290  else
291  *CBlock = (*CBlock & 0xf) | 0xfff0;
294  if (DeviceExt->AvailableClustersValid)
295  InterlockedDecrement((PLONG)&DeviceExt->AvailableClusters);
296  return STATUS_SUCCESS;
297  }
298  }
299  FatLength = StartCluster;
300  StartCluster = 2;
301  }
303  return STATUS_DISK_FULL;
304 }
305 
306 /*
307  * FUNCTION: Finds the first available cluster in a FAT32 table
308  */
309 NTSTATUS
311  PDEVICE_EXTENSION DeviceExt,
312  PULONG Cluster)
313 {
314  ULONG FatLength;
315  ULONG StartCluster;
316  ULONG i, j;
319  PVOID Context;
321  PULONG Block;
322  PULONG BlockEnd;
323 
324  ChunkSize = CACHEPAGESIZE(DeviceExt);
325  FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2);
326  *Cluster = 0;
327  StartCluster = DeviceExt->LastAvailableCluster;
328 
329  for (j = 0; j < 2; j++)
330  {
331  for (i = StartCluster; i < FatLength;)
332  {
333  Offset.QuadPart = ROUND_DOWN(i * 4, ChunkSize);
334  _SEH2_TRY
335  {
336  CcPinRead(DeviceExt->FATFileObject, &Offset, ChunkSize, PIN_WAIT, &Context, &BaseAddress);
337  }
339  {
340  DPRINT1("CcPinRead(Offset %x, Length %u) failed\n", (ULONG)Offset.QuadPart, ChunkSize);
342  }
343  _SEH2_END;
344  Block = (PULONG)((ULONG_PTR)BaseAddress + (i * 4) % ChunkSize);
345  BlockEnd = (PULONG)((ULONG_PTR)BaseAddress + ChunkSize);
346 
347  /* Now process the whole block */
348  while (Block < BlockEnd && i < FatLength)
349  {
350  if ((*Block & 0x0fffffff) == 0)
351  {
352  DPRINT("Found available cluster 0x%x\n", i);
353  DeviceExt->LastAvailableCluster = *Cluster = i;
354  *Block = 0x0fffffff;
357  if (DeviceExt->AvailableClustersValid)
358  InterlockedDecrement((PLONG)&DeviceExt->AvailableClusters);
359  return STATUS_SUCCESS;
360  }
361 
362  Block++;
363  i++;
364  }
365 
367  }
368  FatLength = StartCluster;
369  StartCluster = 2;
370  }
371  return STATUS_DISK_FULL;
372 }
373 
374 /*
375  * FUNCTION: Counts free cluster in a FAT12 table
376  */
377 static
378 NTSTATUS
380  PDEVICE_EXTENSION DeviceExt)
381 {
382  ULONG Entry;
384  ULONG ulCount = 0;
385  ULONG i;
386  ULONG numberofclusters;
388  PVOID Context;
389  PUSHORT CBlock;
390 
391  Offset.QuadPart = 0;
392  _SEH2_TRY
393  {
394  CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector, MAP_WAIT, &Context, &BaseAddress);
395  }
397  {
399  }
400  _SEH2_END;
401 
402  numberofclusters = DeviceExt->FatInfo.NumberOfClusters + 2;
403 
404  for (i = 2; i < numberofclusters; i++)
405  {
406  CBlock = (PUSHORT)((char*)BaseAddress + (i * 12) / 8);
407  if ((i % 2) == 0)
408  {
409  Entry = *CBlock & 0x0fff;
410  }
411  else
412  {
413  Entry = *CBlock >> 4;
414  }
415 
416  if (Entry == 0)
417  ulCount++;
418  }
419 
421  DeviceExt->AvailableClusters = ulCount;
422  DeviceExt->AvailableClustersValid = TRUE;
423 
424  return STATUS_SUCCESS;
425 }
426 
427 
428 /*
429  * FUNCTION: Counts free clusters in a FAT16 table
430  */
431 static
432 NTSTATUS
434  PDEVICE_EXTENSION DeviceExt)
435 {
436  PUSHORT Block;
437  PUSHORT BlockEnd;
439  ULONG ulCount = 0;
440  ULONG i;
442  PVOID Context = NULL;
444  ULONG FatLength;
445 
446  ChunkSize = CACHEPAGESIZE(DeviceExt);
447  FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2);
448 
449  for (i = 2; i < FatLength; )
450  {
451  Offset.QuadPart = ROUND_DOWN(i * 2, ChunkSize);
452  _SEH2_TRY
453  {
454  CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, MAP_WAIT, &Context, &BaseAddress);
455  }
457  {
459  }
460  _SEH2_END;
461  Block = (PUSHORT)((ULONG_PTR)BaseAddress + (i * 2) % ChunkSize);
462  BlockEnd = (PUSHORT)((ULONG_PTR)BaseAddress + ChunkSize);
463 
464  /* Now process the whole block */
465  while (Block < BlockEnd && i < FatLength)
466  {
467  if (*Block == 0)
468  ulCount++;
469  Block++;
470  i++;
471  }
472 
474  }
475 
476  DeviceExt->AvailableClusters = ulCount;
477  DeviceExt->AvailableClustersValid = TRUE;
478 
479  return STATUS_SUCCESS;
480 }
481 
482 
483 /*
484  * FUNCTION: Counts free clusters in a FAT32 table
485  */
486 static
487 NTSTATUS
489  PDEVICE_EXTENSION DeviceExt)
490 {
491  PULONG Block;
492  PULONG BlockEnd;
494  ULONG ulCount = 0;
495  ULONG i;
497  PVOID Context = NULL;
499  ULONG FatLength;
500 
501  ChunkSize = CACHEPAGESIZE(DeviceExt);
502  FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2);
503 
504  for (i = 2; i < FatLength; )
505  {
506  Offset.QuadPart = ROUND_DOWN(i * 4, ChunkSize);
507  _SEH2_TRY
508  {
509  CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, MAP_WAIT, &Context, &BaseAddress);
510  }
512  {
513  DPRINT1("CcMapData(Offset %x, Length %u) failed\n", (ULONG)Offset.QuadPart, ChunkSize);
515  }
516  _SEH2_END;
517  Block = (PULONG)((ULONG_PTR)BaseAddress + (i * 4) % ChunkSize);
518  BlockEnd = (PULONG)((ULONG_PTR)BaseAddress + ChunkSize);
519 
520  /* Now process the whole block */
521  while (Block < BlockEnd && i < FatLength)
522  {
523  if ((*Block & 0x0fffffff) == 0)
524  ulCount++;
525  Block++;
526  i++;
527  }
528 
530  }
531 
532  DeviceExt->AvailableClusters = ulCount;
533  DeviceExt->AvailableClustersValid = TRUE;
534 
535  return STATUS_SUCCESS;
536 }
537 
538 NTSTATUS
540  PDEVICE_EXTENSION DeviceExt,
541  PLARGE_INTEGER Clusters)
542 {
544  ExAcquireResourceExclusiveLite (&DeviceExt->FatResource, TRUE);
545  if (!DeviceExt->AvailableClustersValid)
546  {
547  if (DeviceExt->FatInfo.FatType == FAT12)
548  Status = FAT12CountAvailableClusters(DeviceExt);
549  else if (DeviceExt->FatInfo.FatType == FAT16 || DeviceExt->FatInfo.FatType == FATX16)
550  Status = FAT16CountAvailableClusters(DeviceExt);
551  else
552  Status = FAT32CountAvailableClusters(DeviceExt);
553  }
554  if (Clusters != NULL)
555  {
556  Clusters->QuadPart = DeviceExt->AvailableClusters;
557  }
558  ExReleaseResourceLite (&DeviceExt->FatResource);
559 
560  return Status;
561 }
562 
563 
564 /*
565  * FUNCTION: Writes a cluster to the FAT12 physical and in-memory tables
566  */
567 NTSTATUS
569  PDEVICE_EXTENSION DeviceExt,
570  ULONG ClusterToWrite,
571  ULONG NewValue,
572  PULONG OldValue)
573 {
574  ULONG FATOffset;
575  PUCHAR CBlock;
577  PVOID Context;
579 
580  Offset.QuadPart = 0;
581  _SEH2_TRY
582  {
583  CcPinRead(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector, PIN_WAIT, &Context, &BaseAddress);
584  }
586  {
588  }
589  _SEH2_END;
590  CBlock = (PUCHAR)BaseAddress;
591 
592  FATOffset = (ClusterToWrite * 12) / 8;
593  DPRINT("Writing 0x%x for 0x%x at 0x%x\n",
594  NewValue, ClusterToWrite, FATOffset);
595  if ((ClusterToWrite % 2) == 0)
596  {
597  *OldValue = CBlock[FATOffset] + ((CBlock[FATOffset + 1] & 0x0f) << 8);
598  CBlock[FATOffset] = (UCHAR)NewValue;
599  CBlock[FATOffset + 1] &= 0xf0;
600  CBlock[FATOffset + 1] |= (NewValue & 0xf00) >> 8;
601  }
602  else
603  {
604  *OldValue = (CBlock[FATOffset] >> 4) + (CBlock[FATOffset + 1] << 4);
605  CBlock[FATOffset] &= 0x0f;
606  CBlock[FATOffset] |= (NewValue & 0xf) << 4;
607  CBlock[FATOffset + 1] = (UCHAR)(NewValue >> 4);
608  }
609  /* Write the changed FAT sector(s) to disk */
612  return STATUS_SUCCESS;
613 }
614 
615 /*
616  * FUNCTION: Writes a cluster to the FAT16 physical and in-memory tables
617  */
618 NTSTATUS
620  PDEVICE_EXTENSION DeviceExt,
621  ULONG ClusterToWrite,
622  ULONG NewValue,
623  PULONG OldValue)
624 {
626  ULONG FATOffset;
628  PVOID Context;
630  PUSHORT Cluster;
631 
632  ChunkSize = CACHEPAGESIZE(DeviceExt);
633  FATOffset = ClusterToWrite * 2;
634  Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize);
635  _SEH2_TRY
636  {
637  CcPinRead(DeviceExt->FATFileObject, &Offset, ChunkSize, PIN_WAIT, &Context, &BaseAddress);
638  }
640  {
642  }
643  _SEH2_END;
644 
645  DPRINT("Writing 0x%x for offset 0x%x 0x%x\n", NewValue, FATOffset,
646  ClusterToWrite);
647  Cluster = ((PUSHORT)((char*)BaseAddress + (FATOffset % ChunkSize)));
648  *OldValue = *Cluster;
649  *Cluster = (USHORT)NewValue;
652  return STATUS_SUCCESS;
653 }
654 
655 /*
656  * FUNCTION: Writes a cluster to the FAT32 physical tables
657  */
658 NTSTATUS
660  PDEVICE_EXTENSION DeviceExt,
661  ULONG ClusterToWrite,
662  ULONG NewValue,
663  PULONG OldValue)
664 {
666  ULONG FATOffset;
668  PVOID Context;
670  PULONG Cluster;
671 
672  ChunkSize = CACHEPAGESIZE(DeviceExt);
673 
674  FATOffset = (ClusterToWrite * 4);
675  Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize);
676  _SEH2_TRY
677  {
678  CcPinRead(DeviceExt->FATFileObject, &Offset, ChunkSize, PIN_WAIT, &Context, &BaseAddress);
679  }
681  {
683  }
684  _SEH2_END;
685 
686  DPRINT("Writing 0x%x for offset 0x%x 0x%x\n", NewValue, FATOffset,
687  ClusterToWrite);
688  Cluster = ((PULONG)((char*)BaseAddress + (FATOffset % ChunkSize)));
689  *OldValue = *Cluster & 0x0fffffff;
690  *Cluster = (*Cluster & 0xf0000000) | (NewValue & 0x0fffffff);
691 
694 
695  return STATUS_SUCCESS;
696 }
697 
698 
699 /*
700  * FUNCTION: Write a changed FAT entry
701  */
702 NTSTATUS
704  PDEVICE_EXTENSION DeviceExt,
705  ULONG ClusterToWrite,
706  ULONG NewValue)
707 {
709  ULONG OldValue;
710 
711  ExAcquireResourceExclusiveLite (&DeviceExt->FatResource, TRUE);
712  Status = DeviceExt->WriteCluster(DeviceExt, ClusterToWrite, NewValue, &OldValue);
713  if (DeviceExt->AvailableClustersValid)
714  {
715  if (OldValue && NewValue == 0)
716  InterlockedIncrement((PLONG)&DeviceExt->AvailableClusters);
717  else if (OldValue == 0 && NewValue)
718  InterlockedDecrement((PLONG)&DeviceExt->AvailableClusters);
719  }
720  ExReleaseResourceLite(&DeviceExt->FatResource);
721  return Status;
722 }
723 
724 /*
725  * FUNCTION: Converts the cluster number to a sector number for this physical
726  * device
727  */
728 ULONGLONG
730  PDEVICE_EXTENSION DeviceExt,
731  ULONG Cluster)
732 {
733  return DeviceExt->FatInfo.dataStart +
734  ((ULONGLONG)(Cluster - 2) * DeviceExt->FatInfo.SectorsPerCluster);
735 
736 }
737 
738 /*
739  * FUNCTION: Retrieve the next cluster depending on the FAT type
740  */
741 NTSTATUS
743  PDEVICE_EXTENSION DeviceExt,
744  ULONG CurrentCluster,
746 {
748 
749  DPRINT("GetNextCluster(DeviceExt %p, CurrentCluster %x)\n",
750  DeviceExt, CurrentCluster);
751 
752  if (CurrentCluster == 0)
753  {
754  DPRINT1("WARNING: File system corruption detected. You may need to run a disk repair utility.\n");
756  ASSERT(CurrentCluster != 0);
758  }
759 
760  ExAcquireResourceSharedLite(&DeviceExt->FatResource, TRUE);
761  Status = DeviceExt->GetNextCluster(DeviceExt, CurrentCluster, NextCluster);
762  ExReleaseResourceLite(&DeviceExt->FatResource);
763 
764  return Status;
765 }
766 
767 /*
768  * FUNCTION: Retrieve the next cluster depending on the FAT type
769  */
770 NTSTATUS
772  PDEVICE_EXTENSION DeviceExt,
773  ULONG CurrentCluster,
775 {
776  ULONG NewCluster;
778 
779  DPRINT("GetNextClusterExtend(DeviceExt %p, CurrentCluster %x)\n",
780  DeviceExt, CurrentCluster);
781 
782  ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);
783  /*
784  * If the file hasn't any clusters allocated then we need special
785  * handling
786  */
787  if (CurrentCluster == 0)
788  {
789  Status = DeviceExt->FindAndMarkAvailableCluster(DeviceExt, &NewCluster);
790  if (!NT_SUCCESS(Status))
791  {
792  ExReleaseResourceLite(&DeviceExt->FatResource);
793  return Status;
794  }
795 
796  *NextCluster = NewCluster;
797  ExReleaseResourceLite(&DeviceExt->FatResource);
798  return STATUS_SUCCESS;
799  }
800 
801  Status = DeviceExt->GetNextCluster(DeviceExt, CurrentCluster, NextCluster);
802 
803  if ((*NextCluster) == 0xFFFFFFFF)
804  {
805  /* We are after last existing cluster, we must add one to file */
806  /* Firstly, find the next available open allocation unit and
807  mark it as end of file */
808  Status = DeviceExt->FindAndMarkAvailableCluster(DeviceExt, &NewCluster);
809  if (!NT_SUCCESS(Status))
810  {
811  ExReleaseResourceLite(&DeviceExt->FatResource);
812  return Status;
813  }
814 
815  /* Now, write the AU of the LastCluster with the value of the newly
816  found AU */
817  WriteCluster(DeviceExt, CurrentCluster, NewCluster);
818  *NextCluster = NewCluster;
819  }
820 
821  ExReleaseResourceLite(&DeviceExt->FatResource);
822  return Status;
823 }
824 
825 /*
826  * FUNCTION: Retrieve the dirty status
827  */
828 NTSTATUS
830  PDEVICE_EXTENSION DeviceExt,
831  PBOOLEAN DirtyStatus)
832 {
834 
835  DPRINT("GetDirtyStatus(DeviceExt %p)\n", DeviceExt);
836 
837  /* FAT12 has no dirty bit */
838  if (DeviceExt->FatInfo.FatType == FAT12)
839  {
840  *DirtyStatus = FALSE;
841  return STATUS_SUCCESS;
842  }
843 
844  /* Not really in the FAT, but share the lock because
845  * we're really low-level and shouldn't happent that often
846  * And call the appropriate function
847  */
848  ExAcquireResourceSharedLite(&DeviceExt->FatResource, TRUE);
849  Status = DeviceExt->GetDirtyStatus(DeviceExt, DirtyStatus);
850  ExReleaseResourceLite(&DeviceExt->FatResource);
851 
852  return Status;
853 }
854 
855 NTSTATUS
857  PDEVICE_EXTENSION DeviceExt,
858  PBOOLEAN DirtyStatus)
859 {
861  ULONG Length;
862 #ifdef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
864 #else
865  PVOID Context;
866 #endif
867  struct _BootSector * Sector;
868 
869  /* We'll read the bootsector at 0 */
870  Offset.QuadPart = 0;
871  Length = DeviceExt->FatInfo.BytesPerSector;
872 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
873  /* Go through Cc for this */
874  _SEH2_TRY
875  {
876  CcPinRead(DeviceExt->VolumeFcb->FileObject, &Offset, Length, PIN_WAIT, &Context, (PVOID *)&Sector);
877  }
879  {
881  }
882  _SEH2_END;
883 #else
884  /* No Cc, do it the old way:
885  * - Allocate a big enough buffer
886  * - And read the disk
887  */
889  if (Sector == NULL)
890  {
891  *DirtyStatus = TRUE;
893  }
894 
895  Status = VfatReadDisk(DeviceExt->StorageDevice, &Offset, Length, (PUCHAR)Sector, FALSE);
896  if (!NT_SUCCESS(Status))
897  {
898  *DirtyStatus = TRUE;
899  ExFreePoolWithTag(Sector, TAG_BUFFER);
900  return Status;
901  }
902 #endif
903 
904  /* Make sure we have a boot sector...
905  * FIXME: This check is a bit lame and should be improved
906  */
907  if (Sector->Signatur1 != 0xaa55)
908  {
909  /* Set we are dirty so that we don't attempt anything */
910  *DirtyStatus = TRUE;
911 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
913 #else
914  ExFreePoolWithTag(Sector, TAG_BUFFER);
915 #endif
917  }
918 
919  /* Return the status of the dirty bit */
920  if (Sector->Res1 & FAT_DIRTY_BIT)
921  *DirtyStatus = TRUE;
922  else
923  *DirtyStatus = FALSE;
924 
925 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
927 #else
928  ExFreePoolWithTag(Sector, TAG_BUFFER);
929 #endif
930  return STATUS_SUCCESS;
931 }
932 
933 NTSTATUS
935  PDEVICE_EXTENSION DeviceExt,
936  PBOOLEAN DirtyStatus)
937 {
939  ULONG Length;
940 #ifdef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
942 #else
943  PVOID Context;
944 #endif
945  struct _BootSector32 * Sector;
946 
947  /* We'll read the bootsector at 0 */
948  Offset.QuadPart = 0;
949  Length = DeviceExt->FatInfo.BytesPerSector;
950 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
951  /* Go through Cc for this */
952  _SEH2_TRY
953  {
954  CcPinRead(DeviceExt->VolumeFcb->FileObject, &Offset, Length, PIN_WAIT, &Context, (PVOID *)&Sector);
955  }
957  {
959  }
960  _SEH2_END;
961 #else
962  /* No Cc, do it the old way:
963  * - Allocate a big enough buffer
964  * - And read the disk
965  */
967  if (Sector == NULL)
968  {
969  *DirtyStatus = TRUE;
971  }
972 
973  Status = VfatReadDisk(DeviceExt->StorageDevice, &Offset, Length, (PUCHAR)Sector, FALSE);
974  if (!NT_SUCCESS(Status))
975  {
976  *DirtyStatus = TRUE;
977  ExFreePoolWithTag(Sector, TAG_BUFFER);
978  return Status;
979  }
980 #endif
981 
982  /* Make sure we have a boot sector...
983  * FIXME: This check is a bit lame and should be improved
984  */
985  if (Sector->Signature1 != 0xaa55)
986  {
987  /* Set we are dirty so that we don't attempt anything */
988  *DirtyStatus = TRUE;
989 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
991 #else
992  ExFreePoolWithTag(Sector, TAG_BUFFER);
993 #endif
995  }
996 
997  /* Return the status of the dirty bit */
998  if (Sector->Res4 & FAT_DIRTY_BIT)
999  *DirtyStatus = TRUE;
1000  else
1001  *DirtyStatus = FALSE;
1002 
1003 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1005 #else
1006  ExFreePoolWithTag(Sector, TAG_BUFFER);
1007 #endif
1008  return STATUS_SUCCESS;
1009 }
1010 
1011 /*
1012  * FUNCTION: Set the dirty status
1013  */
1014 NTSTATUS
1016  PDEVICE_EXTENSION DeviceExt,
1017  BOOLEAN DirtyStatus)
1018 {
1019  NTSTATUS Status;
1020 
1021  DPRINT("SetDirtyStatus(DeviceExt %p, DirtyStatus %d)\n", DeviceExt, DirtyStatus);
1022 
1023  /* FAT12 has no dirty bit */
1024  if (DeviceExt->FatInfo.FatType == FAT12)
1025  {
1026  return STATUS_SUCCESS;
1027  }
1028 
1029  /* Not really in the FAT, but share the lock because
1030  * we're really low-level and shouldn't happent that often
1031  * And call the appropriate function
1032  * Acquire exclusive because we will modify ondisk value
1033  */
1034  ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);
1035  Status = DeviceExt->SetDirtyStatus(DeviceExt, DirtyStatus);
1036  ExReleaseResourceLite(&DeviceExt->FatResource);
1037 
1038  return Status;
1039 }
1040 
1041 NTSTATUS
1043  PDEVICE_EXTENSION DeviceExt,
1044  BOOLEAN DirtyStatus)
1045 {
1047  ULONG Length;
1048 #ifdef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1049  NTSTATUS Status;
1050 #else
1051  PVOID Context;
1052 #endif
1053  struct _BootSector * Sector;
1054 
1055  /* We'll read (and then write) the bootsector at 0 */
1056  Offset.QuadPart = 0;
1057  Length = DeviceExt->FatInfo.BytesPerSector;
1058 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1059  /* Go through Cc for this */
1060  _SEH2_TRY
1061  {
1062  CcPinRead(DeviceExt->VolumeFcb->FileObject, &Offset, Length, PIN_WAIT, &Context, (PVOID *)&Sector);
1063  }
1065  {
1067  }
1068  _SEH2_END;
1069 #else
1070  /* No Cc, do it the old way:
1071  * - Allocate a big enough buffer
1072  * - And read the disk
1073  */
1075  if (Sector == NULL)
1076  {
1078  }
1079 
1080  Status = VfatReadDisk(DeviceExt->StorageDevice, &Offset, Length, (PUCHAR)Sector, FALSE);
1081  if (!NT_SUCCESS(Status))
1082  {
1083  ExFreePoolWithTag(Sector, TAG_BUFFER);
1084  return Status;
1085  }
1086 #endif
1087 
1088  /* Make sure we have a boot sector...
1089  * FIXME: This check is a bit lame and should be improved
1090  */
1091  if (Sector->Signatur1 != 0xaa55)
1092  {
1093 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1095 #else
1096  ExFreePoolWithTag(Sector, TAG_BUFFER);
1097 #endif
1099  }
1100 
1101  /* Modify the dirty bit status according
1102  * to caller needs
1103  */
1104  if (!DirtyStatus)
1105  {
1106  Sector->Res1 &= ~FAT_DIRTY_BIT;
1107  }
1108  else
1109  {
1110  Sector->Res1 |= FAT_DIRTY_BIT;
1111  }
1112 
1113 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1114  /* Mark boot sector dirty so that it gets written to the disk */
1117  return STATUS_SUCCESS;
1118 #else
1119  /* Write back the boot sector to the disk */
1120  Status = VfatWriteDisk(DeviceExt->StorageDevice, &Offset, Length, (PUCHAR)Sector, FALSE);
1121  ExFreePoolWithTag(Sector, TAG_BUFFER);
1122  return Status;
1123 #endif
1124 }
1125 
1126 NTSTATUS
1128  PDEVICE_EXTENSION DeviceExt,
1129  BOOLEAN DirtyStatus)
1130 {
1132  ULONG Length;
1133 #ifdef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1134  NTSTATUS Status;
1135 #else
1136  PVOID Context;
1137 #endif
1138  struct _BootSector32 * Sector;
1139 
1140  /* We'll read (and then write) the bootsector at 0 */
1141  Offset.QuadPart = 0;
1142  Length = DeviceExt->FatInfo.BytesPerSector;
1143 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1144  /* Go through Cc for this */
1145  _SEH2_TRY
1146  {
1147  CcPinRead(DeviceExt->VolumeFcb->FileObject, &Offset, Length, PIN_WAIT, &Context, (PVOID *)&Sector);
1148  }
1150  {
1152  }
1153  _SEH2_END;
1154 #else
1155  /* No Cc, do it the old way:
1156  * - Allocate a big enough buffer
1157  * - And read the disk
1158  */
1160  if (Sector == NULL)
1161  {
1163  }
1164 
1165  Status = VfatReadDisk(DeviceExt->StorageDevice, &Offset, Length, (PUCHAR)Sector, FALSE);
1166  if (!NT_SUCCESS(Status))
1167  {
1168  ExFreePoolWithTag(Sector, TAG_BUFFER);
1169  return Status;
1170  }
1171 #endif
1172 
1173  /* Make sure we have a boot sector...
1174  * FIXME: This check is a bit lame and should be improved
1175  */
1176  if (Sector->Signature1 != 0xaa55)
1177  {
1178  ASSERT(FALSE);
1179 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1181 #else
1182  ExFreePoolWithTag(Sector, TAG_BUFFER);
1183 #endif
1185  }
1186 
1187  /* Modify the dirty bit status according
1188  * to caller needs
1189  */
1190  if (!DirtyStatus)
1191  {
1192  Sector->Res4 &= ~FAT_DIRTY_BIT;
1193  }
1194  else
1195  {
1196  Sector->Res4 |= FAT_DIRTY_BIT;
1197  }
1198 
1199 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1200  /* Mark boot sector dirty so that it gets written to the disk */
1203  return STATUS_SUCCESS;
1204 #else
1205  /* Write back the boot sector to the disk */
1206  Status = VfatWriteDisk(DeviceExt->StorageDevice, &Offset, Length, (PUCHAR)Sector, FALSE);
1207  ExFreePoolWithTag(Sector, TAG_BUFFER);
1208  return Status;
1209 #endif
1210 }
1211 
1212 NTSTATUS
1214  PDEVICE_EXTENSION DeviceExt)
1215 {
1217  ULONG Length;
1218 #ifdef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1219  NTSTATUS Status;
1220 #else
1221  PVOID Context;
1222 #endif
1223  struct _FsInfoSector * Sector;
1224 
1225  if (!DeviceExt->AvailableClustersValid)
1226  {
1227  return STATUS_INVALID_PARAMETER;
1228  }
1229 
1230  /* We'll read (and then write) the fsinfo sector */
1231  Offset.QuadPart = DeviceExt->FatInfo.FSInfoSector * DeviceExt->FatInfo.BytesPerSector;
1232  Length = DeviceExt->FatInfo.BytesPerSector;
1233 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1234  /* Go through Cc for this */
1235  _SEH2_TRY
1236  {
1237  CcPinRead(DeviceExt->VolumeFcb->FileObject, &Offset, Length, PIN_WAIT, &Context, (PVOID *)&Sector);
1238  }
1240  {
1242  }
1243  _SEH2_END;
1244 #else
1245  /* No Cc, do it the old way:
1246  * - Allocate a big enough buffer
1247  * - And read the disk
1248  */
1250  if (Sector == NULL)
1251  {
1253  }
1254 
1255  Status = VfatReadDisk(DeviceExt->StorageDevice, &Offset, Length, (PUCHAR)Sector, FALSE);
1256  if (!NT_SUCCESS(Status))
1257  {
1258  ExFreePoolWithTag(Sector, TAG_BUFFER);
1259  return Status;
1260  }
1261 #endif
1262 
1263  /* Make sure we have a FSINFO sector */
1264  if (Sector->ExtBootSignature2 != 0x41615252 ||
1265  Sector->FSINFOSignature != 0x61417272 ||
1266  Sector->Signatur2 != 0xaa550000)
1267  {
1268  ASSERT(FALSE);
1269 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1271 #else
1272  ExFreePoolWithTag(Sector, TAG_BUFFER);
1273 #endif
1275  }
1276 
1277  /* Update the free clusters count */
1278  Sector->FreeCluster = InterlockedCompareExchange((PLONG)&DeviceExt->AvailableClusters, 0, 0);
1279 
1280 #ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
1281  /* Mark FSINFO sector dirty so that it gets written to the disk */
1284  return STATUS_SUCCESS;
1285 #else
1286  /* Write back the FSINFO sector to the disk */
1287  Status = VfatWriteDisk(DeviceExt->StorageDevice, &Offset, Length, (PUCHAR)Sector, FALSE);
1288  ExFreePoolWithTag(Sector, TAG_BUFFER);
1289  return Status;
1290 #endif
1291 }
1292 
1293 /* EOF */
NTSTATUS FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, ULONG NewValue, PULONG OldValue)
Definition: fat.c:568
#define FAT12
Definition: fat.h:167
NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, PULONG CurrentCluster, BOOLEAN Extend)
Definition: rw.c:40
#define TRUE
Definition: types.h:120
NTSTATUS CountAvailableClusters(PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER Clusters)
Definition: fat.c:539
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
struct _Entry Entry
Definition: kefuncs.h:640
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
NTSTATUS FAT16GetDirtyStatus(PDEVICE_EXTENSION DeviceExt, PBOOLEAN DirtyStatus)
Definition: fat.c:856
VOID NTAPI CcSetDirtyPinnedData(IN PVOID BcbVoid, IN OPTIONAL PLARGE_INTEGER Lsn)
Definition: cachesub.c:121
NTSTATUS FAT32UpdateFreeClustersCount(PDEVICE_EXTENSION DeviceExt)
Definition: fat.c:1213
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:1127
NTSTATUS FAT32FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
Definition: fat.c:310
_SEH2_TRY
Definition: create.c:4250
uint32_t ULONG_PTR
Definition: typedefs.h:63
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define STATUS_FILE_CORRUPT_ERROR
Definition: udferr_usr.h:168
NTSTATUS GetDirtyStatus(PDEVICE_EXTENSION DeviceExt, PBOOLEAN DirtyStatus)
Definition: fat.c:829
#define TAG_BUFFER
Definition: vfat.h:545
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_Inout_ PUCHAR _In_ PUCHAR _Out_ PUCHAR _Out_ PULONG ChunkSize
Definition: rtlfuncs.h:2276
static NTSTATUS FAT16CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
Definition: fat.c:433
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
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
NTSTATUS FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, ULONG NewValue, PULONG OldValue)
Definition: fat.c:659
NTSTATUS FAT16FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
Definition: fat.c:171
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
NTSTATUS WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, ULONG NewValue)
Definition: fat.c:703
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
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:771
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
uint64_t ULONGLONG
Definition: typedefs.h:65
static NTSTATUS FAT12CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
Definition: fat.c:379
static NTSTATUS FAT32CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
Definition: fat.c:488
NTSTATUS VfatWriteDisk(IN PDEVICE_OBJECT pDeviceObject, IN PLARGE_INTEGER WriteOffset, IN ULONG WriteLength, IN OUT PUCHAR Buffer, IN BOOLEAN Override)
Definition: blockdev.c:255
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
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
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#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
Status
Definition: gdiplustypes.h:24
#define VFAT_BREAK_ON_CORRUPTION
Definition: vfat.h:401
PVFAT_GLOBAL_DATA VfatGlobalData
Definition: iface.c:40
#define ROUND_DOWN(n, align)
Definition: eventvwr.h:30
NTSTATUS FAT32GetDirtyStatus(PDEVICE_EXTENSION DeviceExt, PBOOLEAN DirtyStatus)
Definition: fat.c:934
NTSTATUS GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:742
_SEH2_END
Definition: create.c:4424
#define InterlockedIncrement
Definition: armddk.h:53
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
ULONG Flags
Definition: vfat.h:407
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:75
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155
#define STATUS_DISK_CORRUPT_ERROR
Definition: udferr_usr.h:147
struct tagContext Context
Definition: acpixf.h:1024
NTSTATUS FAT16SetDirtyStatus(PDEVICE_EXTENSION DeviceExt, BOOLEAN DirtyStatus)
Definition: fat.c:1042
unsigned int ULONG
Definition: retypes.h:1
NTSTATUS FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, ULONG NewValue, PULONG OldValue)
Definition: fat.c:619
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
return STATUS_SUCCESS
Definition: btrfs.c:2966
NTSTATUS SetDirtyStatus(PDEVICE_EXTENSION DeviceExt, BOOLEAN DirtyStatus)
Definition: fat.c:1015
signed int * PLONG
Definition: retypes.h:5
ULONGLONG ClusterToSector(PDEVICE_EXTENSION DeviceExt, ULONG Cluster)
Definition: fat.c:729
unsigned short * PUSHORT
Definition: retypes.h:2
base of all file and directory entries
Definition: entries.h:82
LONGLONG QuadPart
Definition: typedefs.h:112