📄 fat.c
字号:
ThisFatEntOffset = (FatOffset % BytesPerSector);
if (!FatReadVolumeSectors(FatDriveNumber, ThisFatSecNum, 1, (PVOID)FILESYSBUFFER))
{
return FALSE;
}
// Get the fat entry
fat = (*((ULONG *) ((ULONG_PTR)FILESYSBUFFER + ThisFatEntOffset))) & 0x0FFFFFFF;
break;
}
DbgPrint((DPRINT_FILESYSTEM, "FAT entry is 0x%x.\n", fat));
*ClusterPointer = fat;
return TRUE;
}
/*
* FatOpenFile()
* Tries to open the file 'name' and returns true or false
* for success and failure respectively
*/
FILE* FatOpenFile(PCSTR FileName)
{
FAT_FILE_INFO TempFatFileInfo;
PFAT_FILE_INFO FileHandle;
DbgPrint((DPRINT_FILESYSTEM, "FatOpenFile() FileName = %s\n", FileName));
if (!FatLookupFile(FileName, &TempFatFileInfo))
{
return NULL;
}
FileHandle = MmAllocateMemory(sizeof(FAT_FILE_INFO));
if (FileHandle == NULL)
{
return NULL;
}
memcpy(FileHandle, &TempFatFileInfo, sizeof(FAT_FILE_INFO));
return (FILE*)FileHandle;
}
ULONG FatCountClustersInChain(ULONG StartCluster)
{
ULONG ClusterCount = 0;
DbgPrint((DPRINT_FILESYSTEM, "FatCountClustersInChain() StartCluster = %d\n", StartCluster));
while (1)
{
//
// If end of chain then break out of our cluster counting loop
//
if (((FatType == FAT12) && (StartCluster >= 0xff8)) ||
((FatType == FAT16 || FatType == FATX16) && (StartCluster >= 0xfff8)) ||
((FatType == FAT32 || FatType == FATX32) && (StartCluster >= 0x0ffffff8)))
{
break;
}
//
// Increment count
//
ClusterCount++;
//
// Get next cluster
//
if (!FatGetFatEntry(StartCluster, &StartCluster))
{
return 0;
}
}
DbgPrint((DPRINT_FILESYSTEM, "FatCountClustersInChain() ClusterCount = %d\n", ClusterCount));
return ClusterCount;
}
ULONG* FatGetClusterChainArray(ULONG StartCluster)
{
ULONG ClusterCount;
ULONG ArraySize;
ULONG* ArrayPointer;
ULONG Idx;
DbgPrint((DPRINT_FILESYSTEM, "FatGetClusterChainArray() StartCluster = %d\n", StartCluster));
ClusterCount = FatCountClustersInChain(StartCluster) + 1; // Lets get the 0x0ffffff8 on the end of the array
ArraySize = ClusterCount * sizeof(ULONG);
//
// Allocate array memory
//
ArrayPointer = MmAllocateMemory(ArraySize);
if (ArrayPointer == NULL)
{
return NULL;
}
//
// Loop through and set array values
//
for (Idx=0; Idx<ClusterCount; Idx++)
{
//
// Set current cluster
//
ArrayPointer[Idx] = StartCluster;
//
// Don't try to get next cluster for last cluster
//
if (((FatType == FAT12) && (StartCluster >= 0xff8)) ||
((FatType == FAT16 || FatType == FATX16) && (StartCluster >= 0xfff8)) ||
((FatType == FAT32 || FatType == FATX32) && (StartCluster >= 0x0ffffff8)))
{
Idx++;
break;
}
//
// Get next cluster
//
if (!FatGetFatEntry(StartCluster, &StartCluster))
{
MmFreeMemory(ArrayPointer);
return NULL;
}
}
return ArrayPointer;
}
/*
* FatReadCluster()
* Reads the specified cluster into memory
*/
BOOLEAN FatReadCluster(ULONG ClusterNumber, PVOID Buffer)
{
ULONG ClusterStartSector;
ClusterStartSector = ((ClusterNumber - 2) * SectorsPerCluster) + DataSectorStart;
DbgPrint((DPRINT_FILESYSTEM, "FatReadCluster() ClusterNumber = %d Buffer = 0x%x ClusterStartSector = %d\n", ClusterNumber, Buffer, ClusterStartSector));
if (!FatReadVolumeSectors(FatDriveNumber, ClusterStartSector, SectorsPerCluster, (PVOID)FILESYSBUFFER))
{
return FALSE;
}
memcpy(Buffer, (PVOID)FILESYSBUFFER, SectorsPerCluster * BytesPerSector);
return TRUE;
}
/*
* FatReadClusterChain()
* Reads the specified clusters into memory
*/
BOOLEAN FatReadClusterChain(ULONG StartClusterNumber, ULONG NumberOfClusters, PVOID Buffer)
{
ULONG ClusterStartSector;
DbgPrint((DPRINT_FILESYSTEM, "FatReadClusterChain() StartClusterNumber = %d NumberOfClusters = %d Buffer = 0x%x\n", StartClusterNumber, NumberOfClusters, Buffer));
while (NumberOfClusters > 0)
{
DbgPrint((DPRINT_FILESYSTEM, "FatReadClusterChain() StartClusterNumber = %d NumberOfClusters = %d Buffer = 0x%x\n", StartClusterNumber, NumberOfClusters, Buffer));
//
// Calculate starting sector for cluster
//
ClusterStartSector = ((StartClusterNumber - 2) * SectorsPerCluster) + DataSectorStart;
//
// Read cluster into memory
//
if (!FatReadVolumeSectors(FatDriveNumber, ClusterStartSector, SectorsPerCluster, (PVOID)FILESYSBUFFER))
{
return FALSE;
}
memcpy(Buffer, (PVOID)FILESYSBUFFER, SectorsPerCluster * BytesPerSector);
//
// Decrement count of clusters left to read
//
NumberOfClusters--;
//
// Increment buffer address by cluster size
//
Buffer = (PVOID)((ULONG_PTR)Buffer + (SectorsPerCluster * BytesPerSector));
//
// Get next cluster
//
if (!FatGetFatEntry(StartClusterNumber, &StartClusterNumber))
{
return FALSE;
}
//
// If end of chain then break out of our cluster reading loop
//
if (((FatType == FAT12) && (StartClusterNumber >= 0xff8)) ||
((FatType == FAT16 || FatType == FATX16) && (StartClusterNumber >= 0xfff8)) ||
((FatType == FAT32 || FatType == FATX32) && (StartClusterNumber >= 0x0ffffff8)))
{
break;
}
}
return TRUE;
}
/*
* FatReadPartialCluster()
* Reads part of a cluster into memory
*/
BOOLEAN FatReadPartialCluster(ULONG ClusterNumber, ULONG StartingOffset, ULONG Length, PVOID Buffer)
{
ULONG ClusterStartSector;
DbgPrint((DPRINT_FILESYSTEM, "FatReadPartialCluster() ClusterNumber = %d StartingOffset = %d Length = %d Buffer = 0x%x\n", ClusterNumber, StartingOffset, Length, Buffer));
ClusterStartSector = ((ClusterNumber - 2) * SectorsPerCluster) + DataSectorStart;
if (!FatReadVolumeSectors(FatDriveNumber, ClusterStartSector, SectorsPerCluster, (PVOID)FILESYSBUFFER))
{
return FALSE;
}
memcpy(Buffer, (PVOID)((ULONG_PTR)FILESYSBUFFER + StartingOffset), Length);
return TRUE;
}
/*
* FatReadFile()
* Reads BytesToRead from open file and
* returns the number of bytes read in BytesRead
*/
BOOLEAN FatReadFile(FILE *FileHandle, ULONG BytesToRead, ULONG* BytesRead, PVOID Buffer)
{
PFAT_FILE_INFO FatFileInfo = (PFAT_FILE_INFO)FileHandle;
ULONG ClusterNumber;
ULONG OffsetInCluster;
ULONG LengthInCluster;
ULONG NumberOfClusters;
ULONG BytesPerCluster;
DbgPrint((DPRINT_FILESYSTEM, "FatReadFile() BytesToRead = %d Buffer = 0x%x\n", BytesToRead, Buffer));
if (BytesRead != NULL)
{
*BytesRead = 0;
}
//
// If they are trying to read past the
// end of the file then return success
// with BytesRead == 0
//
if (FatFileInfo->FilePointer >= FatFileInfo->FileSize)
{
return TRUE;
}
//
// If they are trying to read more than there is to read
// then adjust the amount to read
//
if ((FatFileInfo->FilePointer + BytesToRead) > FatFileInfo->FileSize)
{
BytesToRead = (FatFileInfo->FileSize - FatFileInfo->FilePointer);
}
//
// Ok, now we have to perform at most 3 calculations
// I'll draw you a picture (using nifty ASCII art):
//
// CurrentFilePointer -+
// |
// +----------------+
// |
// +-----------+-----------+-----------+-----------+
// | Cluster 1 | Cluster 2 | Cluster 3 | Cluster 4 |
// +-----------+-----------+-----------+-----------+
// | |
// +---------------+--------------------+
// |
// BytesToRead -------+
//
// 1 - The first calculation (and read) will align
// the file pointer with the next cluster.
// boundary (if we are supposed to read that much)
// 2 - The next calculation (and read) will read
// in all the full clusters that the requested
// amount of data would cover (in this case
// clusters 2 & 3).
// 3 - The last calculation (and read) would read
// in the remainder of the data requested out of
// the last cluster.
//
BytesPerCluster = SectorsPerCluster * BytesPerSector;
//
// Only do the first read if we
// aren't aligned on a cluster boundary
//
if (FatFileInfo->FilePointer % BytesPerCluster)
{
//
// Do the math for our first read
//
ClusterNumber = (FatFileInfo->FilePointer / BytesPerCluster);
ClusterNumber = FatFileInfo->FileFatChain[ClusterNumber];
OffsetInCluster = (FatFileInfo->FilePointer % BytesPerCluster);
LengthInCluster = (BytesToRead > (BytesPerCluster - OffsetInCluster)) ? (BytesPerCluster - OffsetInCluster) : BytesToRead;
//
// Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
//
if (!FatReadPartialCluster(ClusterNumber, OffsetInCluster, LengthInCluster, Buffer))
{
return FALSE;
}
if (BytesRead != NULL)
{
*BytesRead += LengthInCluster;
}
BytesToRead -= LengthInCluster;
FatFileInfo->FilePointer += LengthInCluster;
Buffer = (PVOID)((ULONG_PTR)Buffer + LengthInCluster);
}
//
// Do the math for our second read (if any data left)
//
if (BytesToRead > 0)
{
//
// Determine how many full clusters we need to read
//
NumberOfClusters = (BytesToRead / BytesPerCluster);
if (NumberOfClusters > 0)
{
ClusterNumber = (FatFileInfo->FilePointer / BytesPerCluster);
ClusterNumber = FatFileInfo->FileFatChain[ClusterNumber];
//
// Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
//
if (!FatReadClusterChain(ClusterNumber, NumberOfClusters, Buffer))
{
return FALSE;
}
if (BytesRead != NULL)
{
*BytesRead += (NumberOfClusters * BytesPerCluster);
}
BytesToRead -= (NumberOfClusters * BytesPerCluster);
FatFileInfo->FilePointer += (NumberOfClusters * BytesPerCluster);
Buffer = (PVOID)((ULONG_PTR)Buffer + (NumberOfClusters * BytesPerCluster));
}
}
//
// Do the math for our third read (if any data left)
//
if (BytesToRead > 0)
{
ClusterNumber = (FatFileInfo->FilePointer / BytesPerCluster);
ClusterNumber = FatFileInfo->FileFatChain[ClusterNumber];
//
// Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
//
if (!FatReadPartialCluster(ClusterNumber, 0, BytesToRead, Buffer))
{
return FALSE;
}
if (BytesRead != NULL)
{
*BytesRead += BytesToRead;
}
FatFileInfo->FilePointer += BytesToRead;
BytesToRead -= BytesToRead;
Buffer = (PVOID)((ULONG_PTR)Buffer + BytesToRead);
}
return TRUE;
}
ULONG FatGetFileSize(FILE *FileHandle)
{
PFAT_FILE_INFO FatFileHandle = (PFAT_FILE_INFO)FileHandle;
DbgPrint((DPRINT_FILESYSTEM, "FatGetFileSize() FileSize = %d\n", FatFileHandle->FileSize));
return FatFileHandle->FileSize;
}
VOID FatSetFilePointer(FILE *FileHandle, ULONG NewFilePointer)
{
PFAT_FILE_INFO FatFileHandle = (PFAT_FILE_INFO)FileHandle;
DbgPrint((DPRINT_FILESYSTEM, "FatSetFilePointer() NewFilePointer = %d\n", NewFilePointer));
FatFileHandle->FilePointer = NewFilePointer;
}
ULONG FatGetFilePointer(FILE *FileHandle)
{
PFAT_FILE_INFO FatFileHandle = (PFAT_FILE_INFO)FileHandle;
DbgPrint((DPRINT_FILESYSTEM, "FatGetFilePointer() FilePointer = %d\n", FatFileHandle->FilePointer));
return FatFileHandle->FilePointer;
}
BOOLEAN FatReadVolumeSectors(ULONG DriveNumber, ULONG SectorNumber, ULONG SectorCount, PVOID Buffer)
{
return CacheReadDiskSectors(DriveNumber, SectorNumber + FatVolumeStartSector, SectorCount, Buffer);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -