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