📄 fat.c
字号:
//
// Check if this is a LFN entry
// If so it needs special handling
//
if (DirEntry->Attr == ATTR_LONG_NAME)
{
//
// Check to see if this is a deleted LFN entry, if so continue
//
if (LfnDirEntry->SequenceNumber & 0x80)
{
continue;
}
//
// Mask off high two bits of sequence number
// and make the sequence number zero-based
//
LfnDirEntry->SequenceNumber &= 0x3F;
LfnDirEntry->SequenceNumber--;
//
// Get all 13 LFN entry characters
//
if (LfnDirEntry->Name0_4[0] != 0xFFFF)
{
LfnNameBuffer[0 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name0_4[0];
}
if (LfnDirEntry->Name0_4[1] != 0xFFFF)
{
LfnNameBuffer[1 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name0_4[1];
}
if (LfnDirEntry->Name0_4[2] != 0xFFFF)
{
LfnNameBuffer[2 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name0_4[2];
}
if (LfnDirEntry->Name0_4[3] != 0xFFFF)
{
LfnNameBuffer[3 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name0_4[3];
}
if (LfnDirEntry->Name0_4[4] != 0xFFFF)
{
LfnNameBuffer[4 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name0_4[4];
}
if (LfnDirEntry->Name5_10[0] != 0xFFFF)
{
LfnNameBuffer[5 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[0];
}
if (LfnDirEntry->Name5_10[1] != 0xFFFF)
{
LfnNameBuffer[6 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[1];
}
if (LfnDirEntry->Name5_10[2] != 0xFFFF)
{
LfnNameBuffer[7 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[2];
}
if (LfnDirEntry->Name5_10[3] != 0xFFFF)
{
LfnNameBuffer[8 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[3];
}
if (LfnDirEntry->Name5_10[4] != 0xFFFF)
{
LfnNameBuffer[9 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[4];
}
if (LfnDirEntry->Name5_10[5] != 0xFFFF)
{
LfnNameBuffer[10 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[5];
}
if (LfnDirEntry->Name11_12[0] != 0xFFFF)
{
LfnNameBuffer[11 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name11_12[0];
}
if (LfnDirEntry->Name11_12[1] != 0xFFFF)
{
LfnNameBuffer[12 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name11_12[1];
}
//DbgPrint((DPRINT_FILESYSTEM, "Dumping long name buffer:\n"));
//DbgDumpBuffer(DPRINT_FILESYSTEM, LfnNameBuffer, 260);
continue;
}
//
// Check for the volume label attribute
// and skip over this entry if found
//
if (DirEntry->Attr & ATTR_VOLUMENAME)
{
memset(ShortNameBuffer, 0, 13 * sizeof(UCHAR));
memset(LfnNameBuffer, 0, 261 * sizeof(UCHAR));
continue;
}
//
// If we get here then we've found a short file name
// entry and LfnNameBuffer contains the long file
// name or zeroes. All we have to do now is see if the
// file name matches either the short or long file name
// and fill in the FAT_FILE_INFO structure if it does
// or zero our buffers and continue looking.
//
//
// Get short file name
//
FatParseShortFileName(ShortNameBuffer, DirEntry);
DbgPrint((DPRINT_FILESYSTEM, "Entry: %d LFN = %s\n", CurrentEntry, LfnNameBuffer));
DbgPrint((DPRINT_FILESYSTEM, "Entry: %d DOS name = %s\n", CurrentEntry, ShortNameBuffer));
//
// See if the file name matches either the short or long name
//
if (((strlen(FileName) == strlen(LfnNameBuffer)) && (_stricmp(FileName, LfnNameBuffer) == 0)) ||
((strlen(FileName) == strlen(ShortNameBuffer)) && (_stricmp(FileName, ShortNameBuffer) == 0))) {
//
// We found the entry, now fill in the FAT_FILE_INFO struct
//
FatFileInfoPointer->FileSize = DirEntry->Size;
FatFileInfoPointer->FilePointer = 0;
DbgPrint((DPRINT_FILESYSTEM, "MSDOS Directory Entry:\n"));
DbgPrint((DPRINT_FILESYSTEM, "FileName[11] = %c%c%c%c%c%c%c%c%c%c%c\n", DirEntry->FileName[0], DirEntry->FileName[1], DirEntry->FileName[2], DirEntry->FileName[3], DirEntry->FileName[4], DirEntry->FileName[5], DirEntry->FileName[6], DirEntry->FileName[7], DirEntry->FileName[8], DirEntry->FileName[9], DirEntry->FileName[10]));
DbgPrint((DPRINT_FILESYSTEM, "Attr = 0x%x\n", DirEntry->Attr));
DbgPrint((DPRINT_FILESYSTEM, "ReservedNT = 0x%x\n", DirEntry->ReservedNT));
DbgPrint((DPRINT_FILESYSTEM, "TimeInTenths = %d\n", DirEntry->TimeInTenths));
DbgPrint((DPRINT_FILESYSTEM, "CreateTime = %d\n", DirEntry->CreateTime));
DbgPrint((DPRINT_FILESYSTEM, "CreateDate = %d\n", DirEntry->CreateDate));
DbgPrint((DPRINT_FILESYSTEM, "LastAccessDate = %d\n", DirEntry->LastAccessDate));
DbgPrint((DPRINT_FILESYSTEM, "ClusterHigh = 0x%x\n", DirEntry->ClusterHigh));
DbgPrint((DPRINT_FILESYSTEM, "Time = %d\n", DirEntry->Time));
DbgPrint((DPRINT_FILESYSTEM, "Date = %d\n", DirEntry->Date));
DbgPrint((DPRINT_FILESYSTEM, "ClusterLow = 0x%x\n", DirEntry->ClusterLow));
DbgPrint((DPRINT_FILESYSTEM, "Size = %d\n", DirEntry->Size));
//
// Get the cluster chain
//
StartCluster = ((ULONG)DirEntry->ClusterHigh << 16) + DirEntry->ClusterLow;
DbgPrint((DPRINT_FILESYSTEM, "StartCluster = 0x%x\n", StartCluster));
FatFileInfoPointer->FileFatChain = FatGetClusterChainArray(StartCluster);
//
// See if memory allocation failed
//
if (FatFileInfoPointer->FileFatChain == NULL)
{
return FALSE;
}
return TRUE;
}
//
// Nope, no match - zero buffers and continue looking
//
memset(ShortNameBuffer, 0, 13 * sizeof(UCHAR));
memset(LfnNameBuffer, 0, 261 * sizeof(UCHAR));
continue;
}
return FALSE;
}
static BOOLEAN FatXSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectorySize, PCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer)
{
ULONG EntryCount;
ULONG CurrentEntry;
PFATX_DIRENTRY DirEntry;
ULONG FileNameLen;
EntryCount = DirectorySize / sizeof(FATX_DIRENTRY);
DbgPrint((DPRINT_FILESYSTEM, "FatXSearchDirectoryBufferForFile() DirectoryBuffer = 0x%x EntryCount = %d FileName = %s\n", DirectoryBuffer, EntryCount, FileName));
FileNameLen = strlen(FileName);
DirEntry = (PFATX_DIRENTRY) DirectoryBuffer;
for (CurrentEntry = 0; CurrentEntry < EntryCount; CurrentEntry++, DirEntry++)
{
if (0xff == DirEntry->FileNameSize)
{
break;
}
if (0xe5 == DirEntry->FileNameSize)
{
continue;
}
if (FileNameLen == DirEntry->FileNameSize &&
0 == _strnicmp(FileName, DirEntry->FileName, FileNameLen))
{
/*
* We found the entry, now fill in the FAT_FILE_INFO struct
*/
FatFileInfoPointer->FileSize = DirEntry->Size;
FatFileInfoPointer->FilePointer = 0;
DbgPrint((DPRINT_FILESYSTEM, "FATX Directory Entry:\n"));
DbgPrint((DPRINT_FILESYSTEM, "FileNameSize = %d\n", DirEntry->FileNameSize));
DbgPrint((DPRINT_FILESYSTEM, "Attr = 0x%x\n", DirEntry->Attr));
DbgPrint((DPRINT_FILESYSTEM, "StartCluster = 0x%x\n", DirEntry->StartCluster));
DbgPrint((DPRINT_FILESYSTEM, "Size = %d\n", DirEntry->Size));
DbgPrint((DPRINT_FILESYSTEM, "Time = %d\n", DirEntry->Time));
DbgPrint((DPRINT_FILESYSTEM, "Date = %d\n", DirEntry->Date));
DbgPrint((DPRINT_FILESYSTEM, "CreateTime = %d\n", DirEntry->CreateTime));
DbgPrint((DPRINT_FILESYSTEM, "CreateDate = %d\n", DirEntry->CreateDate));
DbgPrint((DPRINT_FILESYSTEM, "LastAccessTime = %d\n", DirEntry->LastAccessTime));
DbgPrint((DPRINT_FILESYSTEM, "LastAccessDate = %d\n", DirEntry->LastAccessDate));
/*
* Get the cluster chain
*/
FatFileInfoPointer->FileFatChain = FatGetClusterChainArray(DirEntry->StartCluster);
/*
* See if memory allocation failed
*/
if (NULL == FatFileInfoPointer->FileFatChain)
{
return FALSE;
}
return TRUE;
}
}
return FALSE;
}
/*
* FatLookupFile()
* This function searches the file system for the
* specified filename and fills in a FAT_FILE_INFO structure
* with info describing the file, etc. returns true
* if the file exists or false otherwise
*/
BOOLEAN FatLookupFile(PCSTR FileName, PFAT_FILE_INFO FatFileInfoPointer)
{
UINT i;
ULONG NumberOfPathParts;
CHAR PathPart[261];
PVOID DirectoryBuffer;
ULONG DirectoryStartCluster = 0;
ULONG DirectorySize;
FAT_FILE_INFO FatFileInfo;
DbgPrint((DPRINT_FILESYSTEM, "FatLookupFile() FileName = %s\n", FileName));
memset(FatFileInfoPointer, 0, sizeof(FAT_FILE_INFO));
//
// Figure out how many sub-directories we are nested in
//
NumberOfPathParts = FsGetNumPathParts(FileName);
//
// Loop once for each part
//
for (i=0; i<NumberOfPathParts; i++)
{
//
// Get first path part
//
FsGetFirstNameFromPath(PathPart, FileName);
//
// Advance to the next part of the path
//
for (; (*FileName != '\\') && (*FileName != '/') && (*FileName != '\0'); FileName++)
{
}
FileName++;
//
// Buffer the directory contents
//
DirectoryBuffer = FatBufferDirectory(DirectoryStartCluster, &DirectorySize, (i == 0) );
if (DirectoryBuffer == NULL)
{
return FALSE;
}
//
// Search for file name in directory
//
if (ISFATX(FatType))
{
if (!FatXSearchDirectoryBufferForFile(DirectoryBuffer, DirectorySize, PathPart, &FatFileInfo))
{
MmFreeMemory(DirectoryBuffer);
return FALSE;
}
}
else
{
if (!FatSearchDirectoryBufferForFile(DirectoryBuffer, DirectorySize, PathPart, &FatFileInfo))
{
MmFreeMemory(DirectoryBuffer);
return FALSE;
}
}
MmFreeMemory(DirectoryBuffer);
//
// If we have another sub-directory to go then
// grab the start cluster and free the fat chain array
//
if ((i+1) < NumberOfPathParts)
{
DirectoryStartCluster = FatFileInfo.FileFatChain[0];
MmFreeMemory(FatFileInfo.FileFatChain);
}
}
memcpy(FatFileInfoPointer, &FatFileInfo, sizeof(FAT_FILE_INFO));
return TRUE;
}
/*
* FatParseFileName()
* This function parses a directory entry name which
* is in the form of "FILE EXT" and puts it in Buffer
* in the form of "file.ext"
*/
void FatParseShortFileName(PCHAR Buffer, PDIRENTRY DirEntry)
{
ULONG Idx;
Idx = 0;
RtlZeroMemory(Buffer, 13);
//
// Fixup first character
//
if (DirEntry->FileName[0] == 0x05)
{
DirEntry->FileName[0] = 0xE5;
}
//
// Get the file name
//
while (Idx < 8)
{
if (DirEntry->FileName[Idx] == ' ')
{
break;
}
Buffer[Idx] = DirEntry->FileName[Idx];
Idx++;
}
//
// Get extension
//
if ((DirEntry->FileName[8] != ' '))
{
Buffer[Idx++] = '.';
Buffer[Idx++] = (DirEntry->FileName[8] == ' ') ? '\0' : DirEntry->FileName[8];
Buffer[Idx++] = (DirEntry->FileName[9] == ' ') ? '\0' : DirEntry->FileName[9];
Buffer[Idx++] = (DirEntry->FileName[10] == ' ') ? '\0' : DirEntry->FileName[10];
}
DbgPrint((DPRINT_FILESYSTEM, "FatParseShortFileName() ShortName = %s\n", Buffer));
}
/*
* FatGetFatEntry()
* returns the Fat entry for a given cluster number
*/
BOOLEAN FatGetFatEntry(ULONG Cluster, ULONG* ClusterPointer)
{
ULONG fat = 0;
UINT FatOffset;
UINT ThisFatSecNum;
UINT ThisFatEntOffset;
DbgPrint((DPRINT_FILESYSTEM, "FatGetFatEntry() Retrieving FAT entry for cluster %d.\n", Cluster));
switch(FatType)
{
case FAT12:
FatOffset = Cluster + (Cluster / 2);
ThisFatSecNum = ActiveFatSectorStart + (FatOffset / BytesPerSector);
ThisFatEntOffset = (FatOffset % BytesPerSector);
DbgPrint((DPRINT_FILESYSTEM, "FatOffset: %d\n", FatOffset));
DbgPrint((DPRINT_FILESYSTEM, "ThisFatSecNum: %d\n", ThisFatSecNum));
DbgPrint((DPRINT_FILESYSTEM, "ThisFatEntOffset: %d\n", ThisFatEntOffset));
if (ThisFatEntOffset == (BytesPerSector - 1))
{
if (!FatReadVolumeSectors(FatDriveNumber, ThisFatSecNum, 2, (PVOID)FILESYSBUFFER))
{
return FALSE;
}
}
else
{
if (!FatReadVolumeSectors(FatDriveNumber, ThisFatSecNum, 1, (PVOID)FILESYSBUFFER))
{
return FALSE;
}
}
fat = *((USHORT *) ((ULONG_PTR)FILESYSBUFFER + ThisFatEntOffset));
if (Cluster & 0x0001)
fat = fat >> 4; /* Cluster number is ODD */
else
fat = fat & 0x0FFF; /* Cluster number is EVEN */
break;
case FAT16:
case FATX16:
FatOffset = (Cluster * 2);
ThisFatSecNum = ActiveFatSectorStart + (FatOffset / BytesPerSector);
ThisFatEntOffset = (FatOffset % BytesPerSector);
if (!FatReadVolumeSectors(FatDriveNumber, ThisFatSecNum, 1, (PVOID)FILESYSBUFFER))
{
return FALSE;
}
fat = *((USHORT *) ((ULONG_PTR)FILESYSBUFFER + ThisFatEntOffset));
break;
case FAT32:
case FATX32:
FatOffset = (Cluster * 4);
ThisFatSecNum = ActiveFatSectorStart + (FatOffset / BytesPerSector);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -