⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fat.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:

		//
		// 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 + -