/* * FUNCTION: Retrieve the next FAT16 cluster from the FAT table */ NTSTATUS FAT16GetNextCluster( PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster) { PVOID BaseAddress; ULONG FATOffset; ULONG ChunkSize; PVOID Context; LARGE_INTEGER Offset; ChunkSize = CACHEPAGESIZE(DeviceExt); FATOffset = CurrentCluster * 2; Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize); if (!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, MAP_WAIT, &Context, &BaseAddress)) { return STATUS_UNSUCCESSFUL; } CurrentCluster = *((PUSHORT)((char*)BaseAddress + (FATOffset % ChunkSize))); if (CurrentCluster >= 0xfff8 && CurrentCluster <= 0xffff) CurrentCluster = 0xffffffff; CcUnpinData(Context); *NextCluster = CurrentCluster; return STATUS_SUCCESS; }
NTSTATUS FAT32FindAndMarkAvailableCluster (PDEVICE_EXTENSION DeviceExt, PULONG Cluster) /* * FUNCTION: Finds the first available cluster in a FAT32 table */ { ULONG FatLength; ULONG StartCluster; ULONG i, j; PVOID BaseAddress; ULONG ChunkSize; PVOID Context; LARGE_INTEGER Offset; PULONG Block; PULONG BlockEnd; ChunkSize = CACHEPAGESIZE(DeviceExt); FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2); *Cluster = 0; StartCluster = DeviceExt->LastAvailableCluster; for (j = 0; j < 2; j++) { for (i = StartCluster; i < FatLength;) { Offset.QuadPart = ROUND_DOWN(i * 4, ChunkSize); if(!CcPinRead(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) { DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, ChunkSize); return STATUS_UNSUCCESSFUL; } Block = (PULONG)((ULONG_PTR)BaseAddress + (i * 4) % ChunkSize); BlockEnd = (PULONG)((ULONG_PTR)BaseAddress + ChunkSize); /* Now process the whole block */ while (Block < BlockEnd && i < FatLength) { if ((*Block & 0x0fffffff) == 0) { DPRINT("Found available cluster 0x%x\n", i); DeviceExt->LastAvailableCluster = *Cluster = i; *Block = 0x0fffffff; CcSetDirtyPinnedData(Context, NULL); CcUnpinData(Context); if (DeviceExt->AvailableClustersValid) InterlockedDecrement((PLONG)&DeviceExt->AvailableClusters); return(STATUS_SUCCESS); } Block++; i++; } CcUnpinData(Context); } FatLength = StartCluster; StartCluster = 2; } return (STATUS_DISK_FULL); }
NTSTATUS FAT32GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster) /* * FUNCTION: Retrieve the next FAT32 cluster from the FAT table via a physical * disk read */ { PVOID BaseAddress; ULONG FATOffset; ULONG ChunkSize; PVOID Context; LARGE_INTEGER Offset; ChunkSize = CACHEPAGESIZE(DeviceExt); FATOffset = CurrentCluster * sizeof(ULONG); Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize); if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) { return STATUS_UNSUCCESSFUL; } CurrentCluster = (*(PULONG)((char*)BaseAddress + (FATOffset % ChunkSize))) & 0x0fffffff; if (CurrentCluster >= 0xffffff8 && CurrentCluster <= 0xfffffff) CurrentCluster = 0xffffffff; CcUnpinData(Context); *NextCluster = CurrentCluster; return (STATUS_SUCCESS); }
static NTSTATUS FAT32CountAvailableClusters(PDEVICE_EXTENSION DeviceExt) /* * FUNCTION: Counts free clusters in a FAT32 table */ { PULONG Block; PULONG BlockEnd; PVOID BaseAddress = NULL; ULONG ulCount = 0; ULONG i; ULONG ChunkSize; PVOID Context = NULL; LARGE_INTEGER Offset; ULONG FatLength; ChunkSize = CACHEPAGESIZE(DeviceExt); FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2); for (i = 2; i < FatLength; ) { Offset.QuadPart = ROUND_DOWN(i * 4, ChunkSize); if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) { DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, ChunkSize); return STATUS_UNSUCCESSFUL; } Block = (PULONG)((ULONG_PTR)BaseAddress + (i * 4) % ChunkSize); BlockEnd = (PULONG)((ULONG_PTR)BaseAddress + ChunkSize); /* Now process the whole block */ while (Block < BlockEnd && i < FatLength) { if ((*Block & 0x0fffffff) == 0) ulCount++; Block++; i++; } CcUnpinData(Context); } DeviceExt->AvailableClusters = ulCount; DeviceExt->AvailableClustersValid = TRUE; return(STATUS_SUCCESS); }
/* * FUNCTION: Counts free clusters in a FAT16 table */ static NTSTATUS FAT16CountAvailableClusters( PDEVICE_EXTENSION DeviceExt) { PUSHORT Block; PUSHORT BlockEnd; PVOID BaseAddress = NULL; ULONG ulCount = 0; ULONG i; ULONG ChunkSize; PVOID Context = NULL; LARGE_INTEGER Offset; ULONG FatLength; ChunkSize = CACHEPAGESIZE(DeviceExt); FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2); for (i = 2; i < FatLength; ) { Offset.QuadPart = ROUND_DOWN(i * 2, ChunkSize); if (!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) { return STATUS_UNSUCCESSFUL; } Block = (PUSHORT)((ULONG_PTR)BaseAddress + (i * 2) % ChunkSize); BlockEnd = (PUSHORT)((ULONG_PTR)BaseAddress + ChunkSize); /* Now process the whole block */ while (Block < BlockEnd && i < FatLength) { if (*Block == 0) ulCount++; Block++; i++; } CcUnpinData(Context); } DeviceExt->AvailableClusters = ulCount; DeviceExt->AvailableClustersValid = TRUE; return STATUS_SUCCESS; }