}
}
+typedef struct _DIRECTORY_BUFFER
+{
+ LIST_ENTRY Link;
+ PVOID Volume;
+ ULONG DirectoryStartCluster;
+ ULONG DirectorySize;
+ UCHAR Data[];
+} DIRECTORY_BUFFER, *PDIRECTORY_BUFFER;
+
+LIST_ENTRY DirectoryBufferListHead = {&DirectoryBufferListHead, &DirectoryBufferListHead};
+
PVOID FatBufferDirectory(PFAT_VOLUME_INFO Volume, ULONG DirectoryStartCluster, ULONG *DirectorySize, BOOLEAN RootDirectory)
{
- PVOID DirectoryBuffer;
+ PDIRECTORY_BUFFER DirectoryBuffer;
+ PLIST_ENTRY Entry;
TRACE("FatBufferDirectory() DirectoryStartCluster = %d RootDirectory = %s\n", DirectoryStartCluster, (RootDirectory ? "TRUE" : "FALSE"));
RootDirectory = FALSE;
}
+ /* Search the list for a match */
+ for (Entry = DirectoryBufferListHead.Flink;
+ Entry != &DirectoryBufferListHead;
+ Entry = Entry->Flink)
+ {
+ DirectoryBuffer = CONTAINING_RECORD(Entry, DIRECTORY_BUFFER, Link);
+
+ /* Check if it matches */
+ if ((DirectoryBuffer->Volume == Volume) &&
+ (DirectoryBuffer->DirectoryStartCluster == DirectoryStartCluster))
+ {
+ TRACE("Found cached buffer\n");
+ *DirectorySize = DirectoryBuffer->DirectorySize;
+ return DirectoryBuffer->Data;
+ }
+ }
+
//
// Calculate the size of the directory
//
// Attempt to allocate memory for directory buffer
//
TRACE("Trying to allocate (DirectorySize) %d bytes.\n", *DirectorySize);
- DirectoryBuffer = MmAllocateMemory(*DirectorySize);
+ DirectoryBuffer = MmHeapAlloc(*DirectorySize + sizeof(DIRECTORY_BUFFER));
if (DirectoryBuffer == NULL)
{
//
if (RootDirectory)
{
- if (!FatReadVolumeSectors(Volume, Volume->RootDirSectorStart, Volume->RootDirSectors, DirectoryBuffer))
+ if (!FatReadVolumeSectors(Volume, Volume->RootDirSectorStart, Volume->RootDirSectors, DirectoryBuffer->Data))
{
- MmFreeMemory(DirectoryBuffer);
+ MmHeapFree(DirectoryBuffer);
return NULL;
}
}
else
{
- if (!FatReadClusterChain(Volume, DirectoryStartCluster, 0xFFFFFFFF, DirectoryBuffer))
+ if (!FatReadClusterChain(Volume, DirectoryStartCluster, 0xFFFFFFFF, DirectoryBuffer->Data))
{
- MmFreeMemory(DirectoryBuffer);
+ MmHeapFree(DirectoryBuffer);
return NULL;
}
}
- return DirectoryBuffer;
+ /* Enqueue it in the list */
+ DirectoryBuffer->Volume = Volume;
+ DirectoryBuffer->DirectoryStartCluster = DirectoryStartCluster;
+ DirectoryBuffer->DirectorySize = *DirectorySize;
+ InsertTailList(&DirectoryBufferListHead, &DirectoryBuffer->Link);
+
+ return DirectoryBuffer->Data;
}
BOOLEAN FatSearchDirectoryBufferForFile(PFAT_VOLUME_INFO Volume, PVOID DirectoryBuffer, ULONG DirectorySize, PCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer)
{
if (!FatXSearchDirectoryBufferForFile(Volume, DirectoryBuffer, DirectorySize, PathPart, &FatFileInfo))
{
- MmFreeMemory(DirectoryBuffer);
return ENOENT;
}
}
{
if (!FatSearchDirectoryBufferForFile(Volume, DirectoryBuffer, DirectorySize, PathPart, &FatFileInfo))
{
- MmFreeMemory(DirectoryBuffer);
return ENOENT;
}
}
- MmFreeMemory(DirectoryBuffer);
-
//
// If we have another sub-directory to go then
// grab the start cluster and free the fat chain array
//
if (!(FatFileInfo.Attributes & ATTR_DIRECTORY))
{
- MmFreeMemory(FatFileInfo.FileFatChain);
+ MmHeapFree(FatFileInfo.FileFatChain);
return ENOTDIR;
}
DirectoryStartCluster = FatFileInfo.FileFatChain[0];
+ MmHeapFree(FatFileInfo.FileFatChain);
+ FatFileInfo.FileFatChain = NULL;
}
- MmFreeMemory(FatFileInfo.FileFatChain);
}
memcpy(FatFileInfoPointer, &FatFileInfo, sizeof(FAT_FILE_INFO));
UINT32 FatOffset;
UINT32 ThisFatSecNum;
UINT32 ThisFatEntOffset;
+ ULONG SectorCount;
+ PUCHAR ReadBuffer;
+ BOOLEAN status = TRUE;
//TRACE("FatGetFatEntry() Retrieving FAT entry for cluster %d.\n", Cluster);
+ // We need a buffer for 2 secors
+ ReadBuffer = HeapAllocate(FrLdrTempHeap, 2 * Volume->BytesPerSector, 'xTAF');
+ if (!ReadBuffer)
+ {
+ return FALSE;
+ }
+
switch(Volume->FatType)
{
case FAT12:
if (ThisFatEntOffset == (Volume->BytesPerSector - 1))
{
- if (!FatReadVolumeSectors(Volume, ThisFatSecNum, 2, (PVOID)FILESYSBUFFER))
- {
- return FALSE;
- }
+ SectorCount = 2;
}
else
{
- if (!FatReadVolumeSectors(Volume, ThisFatSecNum, 1, (PVOID)FILESYSBUFFER))
- {
- return FALSE;
- }
+ SectorCount = 1;
+ }
+
+ if (!FatReadVolumeSectors(Volume, ThisFatSecNum, SectorCount, ReadBuffer))
+ {
+ status = FALSE;
+ break;
}
- fat = *((USHORT *) ((ULONG_PTR)FILESYSBUFFER + ThisFatEntOffset));
+ fat = *((USHORT *) (ReadBuffer + ThisFatEntOffset));
fat = SWAPW(fat);
if (Cluster & 0x0001)
fat = fat >> 4; /* Cluster number is ODD */
ThisFatSecNum = Volume->ActiveFatSectorStart + (FatOffset / Volume->BytesPerSector);
ThisFatEntOffset = (FatOffset % Volume->BytesPerSector);
- if (!FatReadVolumeSectors(Volume, ThisFatSecNum, 1, (PVOID)FILESYSBUFFER))
+ if (!FatReadVolumeSectors(Volume, ThisFatSecNum, 1, ReadBuffer))
{
- return FALSE;
+ status = FALSE;
+ break;
}
- fat = *((USHORT *) ((ULONG_PTR)FILESYSBUFFER + ThisFatEntOffset));
+ fat = *((USHORT *) (ReadBuffer + ThisFatEntOffset));
fat = SWAPW(fat);
break;
ThisFatSecNum = Volume->ActiveFatSectorStart + (FatOffset / Volume->BytesPerSector);
ThisFatEntOffset = (FatOffset % Volume->BytesPerSector);
- if (!FatReadVolumeSectors(Volume, ThisFatSecNum, 1, (PVOID)FILESYSBUFFER))
+ if (!FatReadVolumeSectors(Volume, ThisFatSecNum, 1, ReadBuffer))
{
return FALSE;
}
// Get the fat entry
- fat = (*((ULONG *) ((ULONG_PTR)FILESYSBUFFER + ThisFatEntOffset))) & 0x0FFFFFFF;
+ fat = (*((ULONG *) (ReadBuffer + ThisFatEntOffset))) & 0x0FFFFFFF;
fat = SWAPD(fat);
break;
default:
- TRACE("Unknown FAT type %d\n", Volume->FatType);
- return FALSE;
-
+ ERR("Unknown FAT type %d\n", Volume->FatType);
+ status = FALSE;
+ break;
}
//TRACE("FAT entry is 0x%x.\n", fat);
+ HeapFree(FrLdrTempHeap, ReadBuffer, 'xTAF');
+
*ClusterPointer = fat;
- return TRUE;
+ return status;
}
ULONG FatCountClustersInChain(PFAT_VOLUME_INFO Volume, ULONG StartCluster)
//
// Allocate array memory
//
- ArrayPointer = MmAllocateMemory(ArraySize);
+ ArrayPointer = MmHeapAlloc(ArraySize);
if (ArrayPointer == NULL)
{
//
if (!FatGetFatEntry(Volume, StartCluster, &StartCluster))
{
- MmFreeMemory(ArrayPointer);
+ MmHeapFree(ArrayPointer);
return NULL;
}
}
//
// Read cluster into memory
//
- if (!FatReadVolumeSectors(Volume, ClusterStartSector, Volume->SectorsPerCluster, (PVOID)FILESYSBUFFER))
+ if (!FatReadVolumeSectors(Volume, ClusterStartSector, Volume->SectorsPerCluster, Buffer))
{
return FALSE;
}
- memcpy(Buffer, (PVOID)FILESYSBUFFER, Volume->SectorsPerCluster * Volume->BytesPerSector);
-
//
// Decrement count of clusters left to read
//
BOOLEAN FatReadPartialCluster(PFAT_VOLUME_INFO Volume, ULONG ClusterNumber, ULONG StartingOffset, ULONG Length, PVOID Buffer)
{
ULONG ClusterStartSector;
+ ULONG SectorOffset, ReadSize, SectorCount;
+ PUCHAR ReadBuffer;
+ BOOLEAN status = FALSE;
//TRACE("FatReadPartialCluster() ClusterNumber = %d StartingOffset = %d Length = %d Buffer = 0x%x\n", ClusterNumber, StartingOffset, Length, Buffer);
ClusterStartSector = ((ClusterNumber - 2) * Volume->SectorsPerCluster) + Volume->DataSectorStart;
- if (!FatReadVolumeSectors(Volume, ClusterStartSector, Volume->SectorsPerCluster, (PVOID)FILESYSBUFFER))
+ // This is the offset of the data in sectors
+ SectorOffset = (StartingOffset / Volume->BytesPerSector);
+ StartingOffset %= Volume->BytesPerSector;
+
+ // Calculate how many sectors we need to read
+ SectorCount = (StartingOffset + Length + Volume->BytesPerSector - 1) / Volume->BytesPerSector;
+
+ // Calculate rounded up read size
+ ReadSize = SectorCount * Volume->BytesPerSector;
+
+ ReadBuffer = HeapAllocate(FrLdrTempHeap, ReadSize, 'xTAF');
+ if (!ReadBuffer)
+ {
+ return FALSE;
+ }
+
+ if (FatReadVolumeSectors(Volume, ClusterStartSector + SectorOffset, SectorCount, ReadBuffer))
{
- return FALSE;
+ memcpy(Buffer, ReadBuffer + StartingOffset, Length);
+ status = TRUE;
}
- memcpy(Buffer, (PVOID)((ULONG_PTR)FILESYSBUFFER + StartingOffset), Length);
+ HeapFree(FrLdrTempHeap, ReadBuffer, 'xTAF');
- return TRUE;
+ return status;
}
/*
//
// Seek to right position
//
- Position.QuadPart = SectorNumber * 512;
+ Position.QuadPart = (ULONGLONG)SectorNumber * 512;
ret = ArcSeek(Volume->DeviceId, &Position, SeekAbsolute);
if (ret != ESUCCESS)
{
{
PFAT_FILE_INFO FileHandle = FsGetDeviceSpecific(FileId);
+ if (FileHandle->FileFatChain) MmHeapFree(FileHandle->FileFatChain);
MmHeapFree(FileHandle);
return ESUCCESS;