2 * $Id: fat.c,v 1.28 2001/07/13 10:31:14 ekohl Exp $
4 * COPYRIGHT: See COPYING in the top level directory
5 * PROJECT: ReactOS kernel
6 * FILE: services/fs/vfat/fat.c
7 * PURPOSE: VFAT Filesystem
8 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
12 /* INCLUDES *****************************************************************/
14 #include <ddk/ntddk.h>
16 #include <ntos/minmax.h>
23 /* GLOBALS ******************************************************************/
25 #define ROUND_DOWN(N, S) ((N) - ((N) % (S)))
27 #define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->BytesPerCluster > PAGESIZE ? \
28 (pDeviceExt)->BytesPerCluster : PAGESIZE)
30 /* FUNCTIONS ****************************************************************/
33 Fat32GetNextCluster (PDEVICE_EXTENSION DeviceExt
,
37 * FUNCTION: Retrieve the next FAT32 cluster from the FAT table via a physical
43 PCACHE_SEGMENT CacheSeg
;
47 FATOffset
= (DeviceExt
->FATStart
* BLOCKSIZE
) +
48 (CurrentCluster
* sizeof(ULONG
));
50 Status
= CcRosRequestCacheSegment(DeviceExt
->StorageBcb
,
51 PAGE_ROUND_DOWN(FATOffset
),
55 if (!NT_SUCCESS(Status
))
61 Status
= VfatReadSectors(DeviceExt
->StorageDevice
,
62 PAGE_ROUND_DOWN(FATOffset
) / BLOCKSIZE
,
65 if (!NT_SUCCESS(Status
))
67 CcRosReleaseCacheSegment(DeviceExt
->StorageBcb
, CacheSeg
, FALSE
);
72 CurrentCluster
= *(PULONG
)(BaseAddress
+ (FATOffset
% PAGESIZE
));
73 if (CurrentCluster
>= 0xffffff8 && CurrentCluster
<= 0xfffffff)
74 CurrentCluster
= 0xffffffff;
75 CcRosReleaseCacheSegment(DeviceExt
->StorageBcb
, CacheSeg
, TRUE
);
76 *NextCluster
= CurrentCluster
;
77 return (STATUS_SUCCESS
);
81 Fat16GetNextCluster (PDEVICE_EXTENSION DeviceExt
,
85 * FUNCTION: Retrieve the next FAT16 cluster from the FAT table
90 PCACHE_SEGMENT CacheSeg
;
95 ChunkSize
= CACHEPAGESIZE(DeviceExt
);
97 FATOffset
= (DeviceExt
->FATStart
* BLOCKSIZE
) + (CurrentCluster
* 2);
99 Status
= CcRosRequestCacheSegment(DeviceExt
->StorageBcb
,
100 ROUND_DOWN(FATOffset
, ChunkSize
),
104 if (!NT_SUCCESS(Status
))
110 Status
= VfatReadSectors(DeviceExt
->StorageDevice
,
111 ROUND_DOWN(FATOffset
, ChunkSize
) / BLOCKSIZE
,
112 ChunkSize
/ BLOCKSIZE
,
114 if (!NT_SUCCESS(Status
))
116 CcRosReleaseCacheSegment(DeviceExt
->StorageBcb
, CacheSeg
, FALSE
);
121 CurrentCluster
= *((PUSHORT
)(BaseAddress
+ (FATOffset
% ChunkSize
)));
122 if (CurrentCluster
>= 0xfff8 && CurrentCluster
<= 0xffff)
123 CurrentCluster
= 0xffffffff;
124 CcRosReleaseCacheSegment(DeviceExt
->StorageBcb
, CacheSeg
, TRUE
);
125 *NextCluster
= CurrentCluster
;
126 return (STATUS_SUCCESS
);
130 Fat12GetNextCluster (PDEVICE_EXTENSION DeviceExt
,
131 ULONG CurrentCluster
,
134 * FUNCTION: Retrieve the next FAT12 cluster from the FAT table
137 unsigned char* CBlock
;
141 PCACHE_SEGMENT CacheSeg
;
147 Status
= CcRosRequestCacheSegment(DeviceExt
->Fat12StorageBcb
,
152 if (!NT_SUCCESS(Status
))
158 Status
= VfatReadSectors(DeviceExt
->StorageDevice
,
160 DeviceExt
->Boot
->FATSectors
,
162 if (!NT_SUCCESS(Status
))
164 CcRosReleaseCacheSegment(DeviceExt
->Fat12StorageBcb
, CacheSeg
, FALSE
);
168 CBlock
= (PUCHAR
)BaseAddress
;
170 FATOffset
= (CurrentCluster
* 12) / 8; /* first byte containing value */
171 if ((CurrentCluster
% 2) == 0)
173 Entry
= CBlock
[FATOffset
];
174 Entry
|= ((CBlock
[FATOffset
+1] & 0xf)<<8);
178 Entry
= (CBlock
[FATOffset
] >> 4);
179 Entry
|= (CBlock
[FATOffset
+1] << 4);
181 // DPRINT("Entry %x\n",Entry);
182 if (Entry
>= 0xff8 && Entry
<= 0xfff)
184 // DPRINT("Returning %x\n",Entry);
185 *NextCluster
= Entry
;
186 CcRosReleaseCacheSegment(DeviceExt
->Fat12StorageBcb
, CacheSeg
, TRUE
);
187 return Entry
== 0xffffffff ? STATUS_END_OF_FILE
: STATUS_SUCCESS
;
191 FAT16FindAvailableCluster (PDEVICE_EXTENSION DeviceExt
,
194 * FUNCTION: Finds the first available cluster in a FAT16 table
201 PCACHE_SEGMENT CacheSeg
;
206 ChunkSize
= CACHEPAGESIZE(DeviceExt
);
208 FatStart
= DeviceExt
->FATStart
* BLOCKSIZE
;
209 FatLength
= DeviceExt
->Boot
->FATSectors
* BLOCKSIZE
;
213 for (i
= 2; i
< FatLength
; i
+=2)
215 if (((FatStart
+ i
) % ChunkSize
) == 0 || CacheSeg
== NULL
)
217 if (CacheSeg
!= NULL
)
219 CcRosReleaseCacheSegment(DeviceExt
->StorageBcb
, CacheSeg
, TRUE
);
221 Status
= CcRosRequestCacheSegment(DeviceExt
->StorageBcb
,
222 ROUND_DOWN(FatStart
+ i
, ChunkSize
),
226 if (!NT_SUCCESS(Status
))
232 Status
= VfatReadSectors(DeviceExt
->StorageDevice
,
233 ROUND_DOWN(FatStart
+ i
, ChunkSize
)
235 ChunkSize
/ BLOCKSIZE
,
237 if (!NT_SUCCESS(Status
))
239 CcRosReleaseCacheSegment(DeviceExt
->StorageBcb
, CacheSeg
,
245 if (*((PUSHORT
)(BaseAddress
+ ((FatStart
+ i
) % ChunkSize
))) == 0)
247 DPRINT("Found available cluster 0x%x\n", i
);
249 CcRosReleaseCacheSegment(DeviceExt
->StorageBcb
, CacheSeg
, TRUE
);
250 return(STATUS_SUCCESS
);
253 CcRosReleaseCacheSegment(DeviceExt
->StorageBcb
, CacheSeg
, TRUE
);
254 return(STATUS_DISK_FULL
);
258 FAT12FindAvailableCluster (PDEVICE_EXTENSION DeviceExt
, PULONG Cluster
)
260 * FUNCTION: Finds the first available cluster in a FAT12 table
269 PCACHE_SEGMENT CacheSeg
;
271 ULONG numberofclusters
;
275 Status
= CcRosRequestCacheSegment(DeviceExt
->Fat12StorageBcb
,
280 if (!NT_SUCCESS(Status
))
286 Status
= VfatReadSectors(DeviceExt
->StorageDevice
,
288 DeviceExt
->Boot
->FATSectors
,
290 if (!NT_SUCCESS(Status
))
292 CcRosReleaseCacheSegment(DeviceExt
->Fat12StorageBcb
, CacheSeg
, FALSE
);
296 CBlock
= (PUCHAR
)BaseAddress
;
298 numberofclusters
= ((DeviceExt
->Boot
->Sectors
? DeviceExt
->Boot
->Sectors
: DeviceExt
->Boot
->SectorsHuge
)-DeviceExt
->dataStart
)/DeviceExt
->Boot
->SectorsPerCluster
+2;
300 for (i
= 2; i
< numberofclusters
; i
++)
302 FATOffset
= (i
* 12) / 8;
305 Entry
= CBlock
[FATOffset
];
306 Entry
|= ((CBlock
[FATOffset
+ 1] & 0xf) << 8);
310 Entry
= (CBlock
[FATOffset
] >> 4);
311 Entry
|= (CBlock
[FATOffset
+ 1] << 4);
315 DPRINT("Found available cluster 0x%x\n", i
);
317 CcRosReleaseCacheSegment(DeviceExt
->Fat12StorageBcb
, CacheSeg
, TRUE
);
318 return(STATUS_SUCCESS
);
321 CcRosReleaseCacheSegment(DeviceExt
->Fat12StorageBcb
, CacheSeg
, TRUE
);
322 return (STATUS_DISK_FULL
);
326 FAT32FindAvailableCluster (PDEVICE_EXTENSION DeviceExt
, PULONG Cluster
)
328 * FUNCTION: Finds the first available cluster in a FAT32 table
334 ULONG numberofclusters
;
337 Block
= ExAllocatePool (NonPagedPool
, BLOCKSIZE
);
340 numberofclusters
= ((DeviceExt
->Boot
->Sectors
? DeviceExt
->Boot
->Sectors
: DeviceExt
->Boot
->SectorsHuge
)-DeviceExt
->dataStart
)/DeviceExt
->Boot
->SectorsPerCluster
+2;
341 numberofclusters
%= 128;
344 sector
< ((struct _BootSector32
*) (DeviceExt
->Boot
))->FATSectors32
;
347 Status
= VfatReadSectors (DeviceExt
->StorageDevice
,
348 (ULONG
) (DeviceExt
->FATStart
+ sector
), 1,
351 if (!NT_SUCCESS(Status
))
357 if (sector
==((struct _BootSector32
*) (DeviceExt
->Boot
))->FATSectors32
-1)
358 forto
=numberofclusters
;
362 for (i
= 0; i
< forto
; i
++)
367 *Cluster
= (i
+ sector
* 128);
368 return(STATUS_SUCCESS
);
372 /* Give an error message (out of disk space) if we reach here) */
374 return (STATUS_DISK_FULL
);
379 FAT12CountAvailableClusters(PDEVICE_EXTENSION DeviceExt
,
380 PLARGE_INTEGER Clusters
)
382 * FUNCTION: Counts free cluster in a FAT12 table
392 PCACHE_SEGMENT CacheSeg
;
394 ULONG numberofclusters
;
396 ExAcquireResourceSharedLite (&DeviceExt
->FatResource
, TRUE
);
397 Status
= CcRosRequestCacheSegment(DeviceExt
->Fat12StorageBcb
,
402 if (!NT_SUCCESS(Status
))
404 ExReleaseResourceLite (&DeviceExt
->FatResource
);
409 Status
= VfatReadSectors(DeviceExt
->StorageDevice
,
411 DeviceExt
->Boot
->FATSectors
,
413 if (!NT_SUCCESS(Status
))
415 CcRosReleaseCacheSegment(DeviceExt
->Fat12StorageBcb
, CacheSeg
, FALSE
);
416 ExReleaseResourceLite (&DeviceExt
->FatResource
);
420 CBlock
= (PUCHAR
)BaseAddress
;
421 numberofclusters
= ((DeviceExt
->Boot
->Sectors
? DeviceExt
->Boot
->Sectors
: DeviceExt
->Boot
->SectorsHuge
)-DeviceExt
->dataStart
)/DeviceExt
->Boot
->SectorsPerCluster
+2;
423 for (i
= 2; i
< numberofclusters
; i
++)
425 FATOffset
= (i
* 12) / 8;
428 Entry
= CBlock
[FATOffset
];
429 Entry
|= ((CBlock
[FATOffset
+ 1] & 0xf) << 8);
433 Entry
= (CBlock
[FATOffset
] >> 4);
434 Entry
|= (CBlock
[FATOffset
+ 1] << 4);
440 CcRosReleaseCacheSegment(DeviceExt
->Fat12StorageBcb
, CacheSeg
, FALSE
);
441 ExReleaseResourceLite (&DeviceExt
->FatResource
);
443 Clusters
->QuadPart
= ulCount
;
445 return(STATUS_SUCCESS
);
450 FAT16CountAvailableClusters(PDEVICE_EXTENSION DeviceExt
,
451 PLARGE_INTEGER Clusters
)
453 * FUNCTION: Counts free clusters in a FAT16 table
460 ExAcquireResourceSharedLite (&DeviceExt
->FatResource
, TRUE
);
462 Block
= (PUSHORT
) DeviceExt
->FAT
;
463 for (i
= 2; i
< (DeviceExt
->Boot
->FATSectors
* 256); i
++)
469 ExReleaseResourceLite (&DeviceExt
->FatResource
);
471 Clusters
->QuadPart
= ulCount
;
473 return(STATUS_SUCCESS
);
478 FAT32CountAvailableClusters(PDEVICE_EXTENSION DeviceExt
,
479 PLARGE_INTEGER Clusters
)
481 * FUNCTION: Counts free clusters in a FAT32 table
488 ULONG numberofclusters
;
491 ExAcquireResourceSharedLite (&DeviceExt
->FatResource
, TRUE
);
493 Block
= ExAllocatePool (NonPagedPool
, BLOCKSIZE
);
495 numberofclusters
= ((DeviceExt
->Boot
->Sectors
? DeviceExt
->Boot
->Sectors
: DeviceExt
->Boot
->SectorsHuge
)-DeviceExt
->dataStart
)/DeviceExt
->Boot
->SectorsPerCluster
+2;
496 numberofclusters
%= 128;
499 sector
< ((struct _BootSector32
*) (DeviceExt
->Boot
))->FATSectors32
;
502 Status
= VfatReadSectors(DeviceExt
->StorageDevice
,
503 (ULONG
) (DeviceExt
->FATStart
+ sector
), 1,
505 if (!NT_SUCCESS(Status
))
508 ExReleaseResourceLite(&DeviceExt
->FatResource
);
512 if (sector
==((struct _BootSector32
*) (DeviceExt
->Boot
))->FATSectors32
-1)
513 forto
=numberofclusters
;
516 for (i
= 0; i
< forto
; i
++)
523 ExReleaseResourceLite (&DeviceExt
->FatResource
);
525 Clusters
->QuadPart
= ulCount
;
527 return(STATUS_SUCCESS
);
531 FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt
,
532 ULONG ClusterToWrite
,
535 * FUNCTION: Writes a cluster to the FAT12 physical and in-memory tables
545 PCACHE_SEGMENT CacheSeg
;
547 Status
= CcRosRequestCacheSegment(DeviceExt
->Fat12StorageBcb
,
552 if (!NT_SUCCESS(Status
))
558 Status
= VfatReadSectors(DeviceExt
->StorageDevice
,
560 DeviceExt
->Boot
->FATSectors
,
562 if (!NT_SUCCESS(Status
))
564 CcRosReleaseCacheSegment(DeviceExt
->Fat12StorageBcb
, CacheSeg
, FALSE
);
568 CBlock
= (PUCHAR
)BaseAddress
;
570 FATOffset
= (ClusterToWrite
* 12) / 8;
571 DPRINT("Writing 0x%x for 0x%x at 0x%x\n",
572 NewValue
, ClusterToWrite
, FATOffset
);
573 if ((ClusterToWrite
% 2) == 0)
575 CBlock
[FATOffset
] = NewValue
;
576 CBlock
[FATOffset
+ 1] &= 0xf0;
577 CBlock
[FATOffset
+ 1] |= (NewValue
& 0xf00) >> 8;
581 CBlock
[FATOffset
] &= 0x0f;
582 CBlock
[FATOffset
] |= (NewValue
& 0xf) << 4;
583 CBlock
[FATOffset
+ 1] = NewValue
>> 4;
585 /* Write the changed FAT sector(s) to disk */
586 FATsector
= FATOffset
/ BLOCKSIZE
;
587 for (i
= 0; i
< DeviceExt
->Boot
->FATCount
; i
++)
589 if ((FATOffset
% BLOCKSIZE
) == (BLOCKSIZE
- 1)) //entry is on 2 sectors
591 /* FIXME: Check status */
592 VfatWriteSectors (DeviceExt
->StorageDevice
,
593 DeviceExt
->FATStart
+ FATsector
594 + i
* DeviceExt
->Boot
->FATSectors
,
595 2, CBlock
+ FATsector
* 512);
599 /* FIXME: Check status */
600 VfatWriteSectors (DeviceExt
->StorageDevice
,
601 DeviceExt
->FATStart
+ FATsector
602 + i
* DeviceExt
->Boot
->FATSectors
,
603 1, CBlock
+ FATsector
* 512);
606 CcRosReleaseCacheSegment(DeviceExt
->Fat12StorageBcb
, CacheSeg
, TRUE
);
607 return(STATUS_SUCCESS
);
611 FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt
,
612 ULONG ClusterToWrite
,
615 * FUNCTION: Writes a cluster to the FAT16 physical and in-memory tables
620 PCACHE_SEGMENT CacheSeg
;
627 ChunkSize
= CACHEPAGESIZE(DeviceExt
);
629 Start
= DeviceExt
->FATStart
;
631 FATOffset
= (Start
* BLOCKSIZE
) + (ClusterToWrite
* 2);
633 for (i
= 0; i
< DeviceExt
->Boot
->FATCount
; i
++)
635 Status
= CcRosRequestCacheSegment(DeviceExt
->StorageBcb
,
636 ROUND_DOWN(FATOffset
, ChunkSize
),
640 if (!NT_SUCCESS(Status
))
646 Status
= VfatReadSectors(DeviceExt
->StorageDevice
,
647 ROUND_DOWN(FATOffset
, ChunkSize
) / BLOCKSIZE
,
648 ChunkSize
/ BLOCKSIZE
,
650 if (!NT_SUCCESS(Status
))
652 CcRosReleaseCacheSegment(DeviceExt
->StorageBcb
, CacheSeg
, FALSE
);
657 DPRINT("Writing 0x%x for offset 0x%x 0x%x\n", NewValue
, FATOffset
,
659 *((PUSHORT
)(BaseAddress
+ (FATOffset
% ChunkSize
))) = NewValue
;
660 Status
= VfatWriteSectors(DeviceExt
->StorageDevice
,
661 ROUND_DOWN(FATOffset
,ChunkSize
) / BLOCKSIZE
,
662 ChunkSize
/ BLOCKSIZE
,
664 CcRosReleaseCacheSegment(DeviceExt
->StorageBcb
, CacheSeg
, TRUE
);
666 DPRINT("DeviceExt->Boot->FATSectors %d\n",
667 DeviceExt
->Boot
->FATSectors
);
668 FATOffset
= FATOffset
+ DeviceExt
->Boot
->FATSectors
* BLOCKSIZE
;
671 return (STATUS_SUCCESS
);
675 FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt
,
676 ULONG ClusterToWrite
,
679 * FUNCTION: Writes a cluster to the FAT32 physical tables
688 struct _BootSector32
*pBoot
;
689 DbgPrint ("FAT32WriteCluster %u : %u\n", ClusterToWrite
, NewValue
);
690 Block
= ExAllocatePool (NonPagedPool
, BLOCKSIZE
);
691 FATsector
= ClusterToWrite
/ 128;
692 FATeis
= ClusterToWrite
- (FATsector
* 128);
693 /* load sector, change value, then rewrite sector */
694 /* FIXME: Check status */
695 VfatReadSectors (DeviceExt
->StorageDevice
,
696 DeviceExt
->FATStart
+ FATsector
, 1, (UCHAR
*) Block
);
697 Block
[FATeis
] = NewValue
;
698 /* Write the changed FAT sector to disk (all FAT's) */
699 Start
= DeviceExt
->FATStart
+ FATsector
;
700 pBoot
= (struct _BootSector32
*) DeviceExt
->Boot
;
701 for (i
= 0; i
< pBoot
->FATCount
; i
++)
703 /* FIXME: Check status */
704 VfatWriteSectors (DeviceExt
->StorageDevice
, Start
, 1, (UCHAR
*) Block
);
705 Start
+= pBoot
->FATSectors
;
710 return(STATUS_SUCCESS
);
714 WriteCluster(PDEVICE_EXTENSION DeviceExt
,
715 ULONG ClusterToWrite
,
718 * FUNCTION: Write a changed FAT entry
723 if (DeviceExt
->FatType
== FAT16
)
725 Status
= FAT16WriteCluster (DeviceExt
, ClusterToWrite
, NewValue
);
727 else if (DeviceExt
->FatType
== FAT32
)
729 Status
= FAT32WriteCluster (DeviceExt
, ClusterToWrite
, NewValue
);
733 Status
= FAT12WriteCluster (DeviceExt
, ClusterToWrite
, NewValue
);
739 ClusterToSector (PDEVICE_EXTENSION DeviceExt
, unsigned long Cluster
)
741 * FUNCTION: Converts the cluster number to a sector number for this physical
745 return DeviceExt
->dataStart
+
746 ((Cluster
- 2) * DeviceExt
->Boot
->SectorsPerCluster
);
750 VfatRawReadCluster(PDEVICE_EXTENSION DeviceExt
,
755 * FUNCTION: Load a cluster from the physical device
760 if (FirstCluster
== 1)
762 Status
= VfatReadSectors (DeviceExt
->StorageDevice
,
764 DeviceExt
->Boot
->SectorsPerCluster
,
772 Sector
= ClusterToSector (DeviceExt
, Cluster
);
775 Status
= VfatReadSectors (DeviceExt
->StorageDevice
,
776 Sector
, DeviceExt
->Boot
->SectorsPerCluster
,
783 VfatRawWriteCluster(PDEVICE_EXTENSION DeviceExt
,
788 * FUNCTION: Write a cluster to the physical device
794 DPRINT ("VfatWriteCluster(DeviceExt %x, Buffer %x, Cluster %d)\n",
795 DeviceExt
, Buffer
, Cluster
);
797 if (FirstCluster
== 1)
799 Status
= VfatWriteSectors(DeviceExt
->StorageDevice
,
801 DeviceExt
->Boot
->SectorsPerCluster
,
806 Sector
= ClusterToSector(DeviceExt
,
809 Status
= VfatWriteSectors(DeviceExt
->StorageDevice
,
811 DeviceExt
->Boot
->SectorsPerCluster
,
818 GetNextCluster (PDEVICE_EXTENSION DeviceExt
,
819 ULONG CurrentCluster
,
823 * FUNCTION: Retrieve the next cluster depending on the FAT type
829 // DPRINT ("GetNextCluster(DeviceExt %x, CurrentCluster %x)\n",
830 // DeviceExt, CurrentCluster);
834 ExAcquireResourceSharedLite (&DeviceExt
->FatResource
, TRUE
);
838 ExAcquireResourceExclusiveLite (&DeviceExt
->FatResource
, TRUE
);
842 * If the file hasn't any clusters allocated then we need special
845 if (CurrentCluster
== 0 && Extend
)
849 if (DeviceExt
->FatType
== FAT16
)
851 Status
= FAT16FindAvailableCluster (DeviceExt
, &NewCluster
);
852 if (!NT_SUCCESS(Status
))
857 else if (DeviceExt
->FatType
== FAT32
)
859 Status
= FAT32FindAvailableCluster (DeviceExt
, &NewCluster
);
860 if (!NT_SUCCESS(Status
))
867 Status
= FAT12FindAvailableCluster (DeviceExt
, &NewCluster
);
868 if (!NT_SUCCESS(Status
))
873 /* Mark the new AU as the EOF */
874 WriteCluster (DeviceExt
, NewCluster
, 0xFFFFFFFF);
875 *NextCluster
= NewCluster
;
876 ExReleaseResourceLite(&DeviceExt
->FatResource
);
877 return(STATUS_SUCCESS
);
879 else if (CurrentCluster
== 0)
881 ExReleaseResourceLite(&DeviceExt
->FatResource
);
882 return(STATUS_UNSUCCESSFUL
);
885 if (DeviceExt
->FatType
== FAT16
)
887 Status
= Fat16GetNextCluster (DeviceExt
, CurrentCluster
, NextCluster
);
889 else if (DeviceExt
->FatType
== FAT32
)
891 Status
= Fat32GetNextCluster (DeviceExt
, CurrentCluster
, NextCluster
);
895 Status
= Fat12GetNextCluster (DeviceExt
, CurrentCluster
, NextCluster
);
897 if (Extend
&& (*NextCluster
) == 0xFFFFFFFF)
901 /* We are after last existing cluster, we must add one to file */
902 /* Firstly, find the next available open allocation unit */
903 if (DeviceExt
->FatType
== FAT16
)
905 Status
= FAT16FindAvailableCluster (DeviceExt
, &NewCluster
);
906 if (!NT_SUCCESS(Status
))
911 else if (DeviceExt
->FatType
== FAT32
)
913 Status
= FAT32FindAvailableCluster (DeviceExt
, &NewCluster
);
914 if (!NT_SUCCESS(Status
))
921 Status
= FAT12FindAvailableCluster (DeviceExt
, &NewCluster
);
922 if (!NT_SUCCESS(Status
))
927 /* Mark the new AU as the EOF */
928 WriteCluster (DeviceExt
, NewCluster
, 0xFFFFFFFF);
929 /* Now, write the AU of the LastCluster with the value of the newly
931 WriteCluster (DeviceExt
, CurrentCluster
, NewCluster
);
932 *NextCluster
= NewCluster
;
935 ExReleaseResourceLite (&DeviceExt
->FatResource
);
941 GetNextSector (PDEVICE_EXTENSION DeviceExt
,
945 /* Some functions don't have access to the cluster they're really reading from.
946 Maybe this is a dirty solution, but it will allow them to handle fragmentation. */
950 DPRINT ("GetNextSector(DeviceExt %x, CurrentSector %x)\n",DeviceExt
, CurrentSector
);
951 if (CurrentSector
<DeviceExt
->dataStart
|| ((CurrentSector
- DeviceExt
->dataStart
+ 1) % DeviceExt
-> Boot
-> SectorsPerCluster
))
952 /* Basically, if the next sequential sector would be on a cluster border, then we'll need to check in the FAT */
954 (*NextSector
)=CurrentSector
+1;
955 return (STATUS_SUCCESS
);
959 CurrentSector
= (CurrentSector
- DeviceExt
->dataStart
) / DeviceExt
-> Boot
-> SectorsPerCluster
+ 2;
961 Status
= GetNextCluster(DeviceExt
, CurrentSector
, NextSector
, Extend
);
962 if (!NT_SUCCESS(Status
))
966 if ((*NextSector
) == 0 || (*NextSector
) == 0xffffffff)
968 /* The caller wants to know a sector. These FAT codes don't correspond to any sector. */
969 return (STATUS_UNSUCCESSFUL
);
972 (*NextSector
)=ClusterToSector(DeviceExt
,(*NextSector
));
973 return (STATUS_SUCCESS
);