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

📄 ffs.c

📁 FSD file system driver
💻 C
📖 第 1 页 / 共 4 页
字号:
/* 
 * FFS File System Driver for Windows
 *
 * ffs.c
 *
 * 2004.5.6 ~
 *
 * Lee Jae-Hong, http://www.pyrasis.com
 *
 * See License.txt
 *
 */

#include "ntifs.h"
#include "ffsdrv.h"


/* Globals */
extern PFFS_GLOBAL   FFSGlobal;


/* Definitions */

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FFSLoadSuper)
#pragma alloc_text(PAGE, FFSSaveSuper)

#pragma alloc_text(PAGE, FFSLoadGroup)
#pragma alloc_text(PAGE, FFSSaveGroup)

#pragma alloc_text(PAGE, FFSv1GetInodeLba)
#pragma alloc_text(PAGE, FFSv2GetInodeLba)
#pragma alloc_text(PAGE, FFSv1LoadInode)
#pragma alloc_text(PAGE, FFSv2LoadInode)
#pragma alloc_text(PAGE, FFSv1SaveInode)
#pragma alloc_text(PAGE, FFSv2SaveInode)

#pragma alloc_text(PAGE, FFSv1LoadBlock)
#pragma alloc_text(PAGE, FFSv2LoadBlock)
#pragma alloc_text(PAGE, FFSSaveBlock)

#pragma alloc_text(PAGE, FFSSaveBuffer)

#pragma alloc_text(PAGE, FFSv1GetBlock)
#pragma alloc_text(PAGE, FFSv2GetBlock)
#pragma alloc_text(PAGE, FFSv1BlockMap)
#pragma alloc_text(PAGE, FFSv2BlockMap)

#pragma alloc_text(PAGE, FFSv1BuildBDL)
#pragma alloc_text(PAGE, FFSv2BuildBDL)

#pragma alloc_text(PAGE, FFSNewBlock)
#pragma alloc_text(PAGE, FFSFreeBlock)

#pragma alloc_text(PAGE, FFSExpandBlock)
#pragma alloc_text(PAGE, FFSExpandInode)

#pragma alloc_text(PAGE, FFSNewInode)
#pragma alloc_text(PAGE, FFSFreeInode)

#pragma alloc_text(PAGE, FFSAddEntry)
#pragma alloc_text(PAGE, FFSRemoveEntry)

#pragma alloc_text(PAGE, FFSTruncateBlock)
#pragma alloc_text(PAGE, FFSTruncateInode)

#pragma alloc_text(PAGE, FFSAddMcbEntry)
#pragma alloc_text(PAGE, FFSRemoveMcbEntry)
#pragma alloc_text(PAGE, FFSLookupMcbEntry)

#endif


PFFS_SUPER_BLOCK
FFSLoadSuper(
	IN PFFS_VCB       Vcb,
	IN BOOLEAN        bVerify,
	IN ULONGLONG      SuperBlockOffset)
{
	NTSTATUS         Status;
	PFFS_SUPER_BLOCK FFSSb = NULL;

	FFSSb = (PFFS_SUPER_BLOCK)ExAllocatePool(PagedPool, SUPER_BLOCK_SIZE);
	if (!FFSSb)
	{
		return NULL;
	}

	Status = FFSReadDisk(Vcb,
				SuperBlockOffset,
				SUPER_BLOCK_SIZE,
				(PVOID)FFSSb,
				bVerify);

	if (!NT_SUCCESS(Status))
	{
		FFSPrint((DBG_ERROR, "FFSLoadSuper: Read Block Device error.\n"));

		ExFreePool(FFSSb);
		return NULL;
	}

	return FFSSb;
}


BOOLEAN
FFSSaveSuper(
	IN PFFS_IRP_CONTEXT    IrpContext,
	IN PFFS_VCB            Vcb)
{
	LONGLONG    Offset;
	BOOLEAN     bRet;

	Offset = (LONGLONG) SUPER_BLOCK_OFFSET;

	bRet = FFSSaveBuffer(IrpContext,
				Vcb,
				Offset,
				SUPER_BLOCK_SIZE,
				Vcb->ffs_super_block);

	if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK))
	{
		FFSStartFloppyFlushDpc(Vcb, NULL, NULL);
	}

	return bRet;
}


#if 0
BOOLEAN
FFSLoadGroup(
	IN PFFS_VCB Vcb)
{
	ULONG       Size;
	PVOID       Buffer;
	LONGLONG    Lba;
	NTSTATUS    Status;

	PFFS_SUPER_BLOCK FFSSb;

	FFSSb = Vcb->ffs_super_block;

	Vcb->BlockSize  = FFSSb->fs_bsize;
	Vcb->SectorBits = FFSLog2(SECTOR_SIZE);
	ASSERT(BLOCK_BITS == FFSLog2(BLOCK_SIZE));

	Vcb->ffs_groups = (FFSSb->s_blocks_count - FFSSb->s_first_data_block +
			FFSSb->s_blocks_per_group - 1) / FFSSb->s_blocks_per_group;

	Size = sizeof(FFS_GROUP_DESC) * Vcb->ffs_groups;

	if (Vcb->BlockSize == MINBSIZE)
	{
		Lba = (LONGLONG)2 * Vcb->BlockSize;
	}

	if (Vcb->BlockSize > MINBSIZE)
	{
		Lba = (LONGLONG)(Vcb->BlockSize);
	}

	if (Lba == 0)
	{
		return FALSE;
	}

	Buffer = ExAllocatePool(PagedPool, Size);
	if (!Buffer)
	{
		FFSPrint((DBG_ERROR, "FFSLoadSuper: no enough memory.\n"));
		return FALSE;
	}

	FFSPrint((DBG_INFO, "FFSLoadGroup: Lba=%I64xh Size=%xh\n", Lba, Size));

	Status = FFSReadDisk(Vcb,
				Lba,
				Size,
				Buffer,
				FALSE);

	if (!NT_SUCCESS(Status))
	{
		ExFreePool(Buffer);
		Buffer = NULL;

		return FALSE;
	}

	Vcb->ffs_group_desc = (PFFS_GROUP_DESC) Buffer;

	return TRUE;
}


BOOLEAN
FFSSaveGroup(
	IN PFFS_IRP_CONTEXT    IrpContext,
	IN PFFS_VCB            Vcb)
{
	LONGLONG    Offset;
	ULONG       Len;
	BOOLEAN     bRet;

	if (Vcb->BlockSize == FFS_MIN_BLOCK) {

		Offset = (LONGLONG)(2 * Vcb->BlockSize);

	} else {

		Offset = (LONGLONG)(Vcb->BlockSize);
	}

	Len = (ULONG)(sizeof(struct ffs_group_desc) * Vcb->ffs_groups);

	bRet = FFSSaveBuffer(IrpContext, Vcb, Offset,
			Len, Vcb->ffs_group_desc);

	if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK))
	{
		FFSStartFloppyFlushDpc(Vcb, NULL, NULL);
	}

	return bRet;
}
#endif


BOOLEAN
FFSv1GetInodeLba(
	IN PFFS_VCB   Vcb,
	IN  ULONG     inode,
	OUT PLONGLONG offset)
{
	LONGLONG loc;

#if 0
	if (inode < 1 || inode > INODES_COUNT)
	{
		FFSPrint((DBG_ERROR, "FFSv1GetInodeLba: Inode value %xh is invalid.\n",inode));
		*offset = 0;
		return FALSE;
	}
#endif

	loc = cgimin(Vcb->ffs_super_block, ino_to_cg(Vcb->ffs_super_block, inode)) 
		* Vcb->ffs_super_block->fs_fsize + ((inode % Vcb->ffs_super_block->fs_ipg) * 128);

	*offset = loc;
	KdPrint(("FFSv1GetInodeLba() inode : %d, loc : %x, offset : %x\n", inode, loc, offset));

	return TRUE;
}


BOOLEAN
FFSv2GetInodeLba(
	IN PFFS_VCB   Vcb,
	IN  ULONG     inode,
	OUT PLONGLONG offset)
{
	LONGLONG loc;

#if 0
	if (inode < 1 || inode > INODES_COUNT)
	{
		FFSPrint((DBG_ERROR, "FFSv2GetInodeLba: Inode value %xh is invalid.\n",inode));
		*offset = 0;
		return FALSE;
	}
#endif

	loc = cgimin(Vcb->ffs_super_block, ino_to_cg(Vcb->ffs_super_block, inode)) 
		* Vcb->ffs_super_block->fs_fsize + ((inode % Vcb->ffs_super_block->fs_ipg) * 256);

	*offset = loc;
	//KdPrint(("FFSv2GetInodeLba() inode : %d, loc : %x, offset : %x\n", inode, loc, offset));

	return TRUE;
}


BOOLEAN
FFSv1LoadInode(
	IN PFFS_VCB     Vcb,
	IN ULONG        inode,
	IN PFFSv1_INODE dinode1)
{
	IO_STATUS_BLOCK     IoStatus;
	LONGLONG            Offset; 

	if (!FFSv1GetInodeLba(Vcb, inode, &Offset))
	{
		FFSPrint((DBG_ERROR, "FFSv1LoadInode: error get inode(%xh)'s addr.\n", inode));
		return FALSE;
	}

	if (!FFSCopyRead(
				Vcb->StreamObj,
				(PLARGE_INTEGER)&Offset,
				DINODE1_SIZE,
				PIN_WAIT,
				(PVOID)dinode1,
				&IoStatus));

	if (!NT_SUCCESS(IoStatus.Status))
	{
		return FALSE;
	}

	return TRUE;
}


BOOLEAN
FFSv2LoadInode(
	IN PFFS_VCB     Vcb,
	IN ULONG        inode,
	IN PFFSv2_INODE dinode2)
{
	IO_STATUS_BLOCK     IoStatus;
	LONGLONG            Offset; 

	if (!FFSv2GetInodeLba(Vcb, inode, &Offset))
	{
		FFSPrint((DBG_ERROR, "FFSv2LoadInode: error get inode(%xh)'s addr.\n", inode));
		return FALSE;
	}

	Offset += (LONGLONG)FFSGlobal->FSOffset[FFSGlobal->PartitionNumber];

	if (!FFSCopyRead(
				Vcb->StreamObj,
				(PLARGE_INTEGER)&Offset,
				DINODE2_SIZE,
				PIN_WAIT,
				(PVOID)dinode2,
				&IoStatus));

	if (!NT_SUCCESS(IoStatus.Status))
	{
		return FALSE;
	}

	return TRUE;
}


/*
BOOLEAN
FFSSaveInode(
	IN PFFS_VCB      Vcb,
	IN ULONG         inode,
	IN struct dinode *dinode)
{
	ULONG       lba;
	ULONG       offset;
	NTSTATUS    Status;

	if (!FFSGetInodeLba(Vcb, inode, &lba, &offset))
	{
		FFSPrint((DBG_ERROR, "FFSLoadInode: error get inode(%xh)'s addr.\n", inode));
		return FALSE;
	}

	Status = FFSWriteDisk(Vcb->TargetDeviceObject,
		lba,
		offset,
		sizeof(FFS_INODE),
		(PVOID)dinode);

	if (!NT_SUCCESS(Status))
	{
		return FALSE;
	}

	return TRUE;
}
*/


BOOLEAN
FFSv1SaveInode(
	IN PFFS_IRP_CONTEXT IrpContext,
	IN PFFS_VCB         Vcb,
	IN ULONG            Inode,
	IN PFFSv1_INODE     dinode1)
{
	LONGLONG        Offset = 0;
	LARGE_INTEGER   CurrentTime;
	BOOLEAN         bRet;

	KeQuerySystemTime(&CurrentTime);
	dinode1->di_mtime = dinode1->di_atime = 
		(ULONG)(FFSInodeTime(CurrentTime));

	FFSPrint((DBG_INFO, "FFSv1SaveInode: Saving Inode %xh: Mode=%xh Size=%xh\n",
				Inode, dinode1->di_mode, dinode1->di_size));

	if (!FFSv1GetInodeLba(Vcb, Inode, &Offset))
	{
		FFSPrint((DBG_ERROR, "FFSv1SaveInode: error get inode(%xh)'s addr.\n", Inode));
		return FALSE;
	}

	bRet = FFSSaveBuffer(IrpContext, Vcb, Offset, DINODE1_SIZE, dinode1);

	if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK))
	{
		FFSStartFloppyFlushDpc(Vcb, NULL, NULL);
	}

	return bRet;
}


BOOLEAN
FFSv2SaveInode(
	IN PFFS_IRP_CONTEXT IrpContext,
	IN PFFS_VCB         Vcb,
	IN ULONG            Inode,
	IN PFFSv2_INODE     dinode2)
{
	return FALSE;
}


BOOLEAN
FFSv1LoadBlock(
	IN PFFS_VCB  Vcb,
	IN ULONG     dwBlk,
	IN PVOID     Buffer)
{
	IO_STATUS_BLOCK     IoStatus;
	LONGLONG            Offset; 

	Offset = (LONGLONG) dwBlk;
	Offset = Offset * SUPER_BLOCK->fs_fsize; // fragment size

	if (!FFSCopyRead(
				Vcb->StreamObj,
				(PLARGE_INTEGER)&Offset,
				Vcb->BlockSize,
				PIN_WAIT,
				Buffer,
				&IoStatus));

	if (!NT_SUCCESS(IoStatus.Status))
	{
		return FALSE;
	}

	return TRUE;
}


BOOLEAN
FFSv2LoadBlock(
	IN PFFS_VCB  Vcb,
	IN ULONGLONG dwBlk,
	IN PVOID     Buffer)
{
	IO_STATUS_BLOCK     IoStatus;
	LONGLONG            Offset; 

	Offset = (LONGLONG)dwBlk;
	Offset = Offset * SUPER_BLOCK->fs_fsize; // fragment size

	Offset += FFSGlobal->FSOffset[FFSGlobal->PartitionNumber];

	if (!FFSCopyRead(
				Vcb->StreamObj,
				(PLARGE_INTEGER)&Offset,
				Vcb->BlockSize,
				PIN_WAIT,
				Buffer,
				&IoStatus));

	if (!NT_SUCCESS(IoStatus.Status))
	{
		return FALSE;
	}

	return TRUE;
}


BOOLEAN
FFSSaveBlock(
	IN PFFS_IRP_CONTEXT IrpContext,
	IN PFFS_VCB         Vcb,
	IN ULONG            dwBlk,
	IN PVOID            Buf)
{
	LONGLONG Offset;
	BOOLEAN  bRet;

	Offset = (LONGLONG)dwBlk;
	Offset = Offset * Vcb->BlockSize;

	bRet = FFSSaveBuffer(IrpContext, Vcb, Offset, Vcb->BlockSize, Buf);

	if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK))
	{
		FFSStartFloppyFlushDpc(Vcb, NULL, NULL);
	}

	return bRet;
}


BOOLEAN
FFSSaveBuffer(
	IN PFFS_IRP_CONTEXT IrpContext,
	IN PFFS_VCB         Vcb,
	IN LONGLONG         Offset,
	IN ULONG            Size,
	IN PVOID            Buf)
{
	PBCB        Bcb;
	PVOID       Buffer;

	if(!CcPinRead(Vcb->StreamObj,
				(PLARGE_INTEGER) (&Offset),
				Size,
				PIN_WAIT,
				&Bcb,
				&Buffer))
	{
		FFSPrint((DBG_ERROR, "FFSSaveBuffer: PinReading error ...\n"));
		return FALSE;
	}


	FFSPrint((DBG_INFO, "FFSSaveBuffer: Off=%I64xh Len=%xh Bcb=%xh\n",
				Offset, Size, (ULONG)Bcb));

	RtlCopyMemory(Buffer, Buf, Size);
	CcSetDirtyPinnedData(Bcb, NULL);

	FFSRepinBcb(IrpContext, Bcb);

	CcUnpinData(Bcb);

	SetFlag(Vcb->StreamObj->Flags, FO_FILE_MODIFIED);

	FFSAddMcbEntry(Vcb, Offset, (LONGLONG)Size);

	return TRUE;
}


ULONG
FFSv1GetBlock(
	IN PFFS_VCB Vcb,
	ULONG       dwContent,
	ULONG       Index,
	int         layer)
{
	ULONG       *pData = NULL;
	ULONG       i = 0, j = 0, temp = 1;
	ULONG       dwBlk = 0;

	if (layer == 0)
	{
		dwBlk = dwContent;
	}
	else if (layer <= 3)
	{
		pData = (ULONG *)ExAllocatePool(PagedPool,
				Vcb->BlockSize);
		if (!pData)
		{
			FFSPrint((DBG_ERROR, "FFSGetBlock: no enough memory.\n"));
			return dwBlk;
		}

		KdPrint(("FFSGetBlock Index : %d, dwContent : %x, layer : %d\n", Index, dwContent, layer));

		if (!FFSv1LoadBlock(Vcb, dwContent, pData))
		{
			ExFreePool(pData);
			return 0;
		}

		temp = 1 << ((BLOCK_BITS - 2) * (layer - 1));

		i = Index / temp;
		j = Index % temp;

		dwBlk = pData[i];

		ExFreePool(pData);

		dwBlk = FFSv1GetBlock(Vcb, dwBlk, j, layer - 1);
	}

	return dwBlk;
}


ULONGLONG
FFSv2GetBlock(
	IN PFFS_VCB Vcb,
	ULONGLONG   dwContent,
	ULONG       Index,
	int         layer)
{
	ULONGLONG   *pData = NULL;
	ULONG       i = 0, j = 0, temp = 1;
	ULONGLONG   dwBlk = 0;

	if (layer == 0)
	{
		dwBlk = dwContent;
	}
	else if (layer <= 3)
	{
		pData = (ULONGLONG *)ExAllocatePool(PagedPool,
				Vcb->BlockSize);
		if (!pData)
		{
			FFSPrint((DBG_ERROR, "FFSv2GetBlock: no enough memory.\n"));
			return dwBlk;
		}

		KdPrint(("FFSv2GetBlock Index : %d, dwContent : %x, layer : %d\n", Index, dwContent, layer));

		if (!FFSv2LoadBlock(Vcb, dwContent, pData))
		{
			ExFreePool(pData);
			return 0;
		}

		if (Index >= (Vcb->BlockSize / 8) && layer == 2)
			temp = 1 << ((BLOCK_BITS - 3) * (layer - 1));
		else
			temp = 1 << ((BLOCK_BITS - 2) * (layer - 1));

		i = Index / temp;
		j = Index % temp;

		dwBlk = pData[i];

		ExFreePool(pData);

		dwBlk = FFSv2GetBlock(Vcb, dwBlk, j, layer - 1);
	}

	return dwBlk;
}


ULONG
FFSv1BlockMap(
	IN PFFS_VCB     Vcb,
	IN PFFSv1_INODE dinode1,
	IN ULONG        Index)
{
	ULONG   dwSizes[FFS_BLOCK_TYPES];
	int     i;
	ULONG   dwBlk;
	ULONG   Totalblocks;

	for (i = 0; i < FFS_BLOCK_TYPES; i++)
	{
		dwSizes[i] = Vcb->dwData[i];
	}

	Totalblocks = (dinode1->di_blocks);

	if (Index >= FFSDataBlocks(Vcb, Totalblocks))
	{
		FFSPrint((DBG_ERROR, "FFSv1BlockMap: error input paramters.\n"));

		FFSBreakPoint();

		return 0;
	}	

	/* 流立, 埃立, 2吝 埃立 贸府 */
	for (i = 0; i < FFS_BLOCK_TYPES; i++)
	{
		if (Index < dwSizes[i])
		{
			if (i == 0)
				dwBlk = dinode1->di_db[Index]; /* 流立 */
			else
				dwBlk = dinode1->di_ib[i - 1]; /* 埃立 */
#if DBG
			{   
				ULONG dwRet = FFSv1GetBlock(Vcb, dwBlk, Index , i);

				KdPrint(("FFSv1BlockMap: i : %d, Index : %d, dwBlk : %x, Data Block : %X\n", i, Index, dwRet, (dwRet * 0x400)));

				return dwRet;
			}
#else
			return FFSv1GetBlock(Vcb, dwBlk, Index , i);
#endif
		}

		Index -= dwSizes[i];
	}

	return 0;
}


ULONGLONG
FFSv2BlockMap(
	IN PFFS_VCB     Vcb,
	IN PFFSv2_INODE dinode2,
	IN ULONG        Index)
{
	ULONG     dwSizes[FFS_BLOCK_TYPES];
	int       i;
	ULONGLONG dwBlk;
	ULONG     Totalblocks;

	for (i = 0; i < FFS_BLOCK_TYPES; i++)
	{
		dwSizes[i] = Vcb->dwData[i];
	}

	Totalblocks = (ULONG)(dinode2->di_blocks);

	if (Index >= FFSDataBlocks(Vcb, Totalblocks))
	{
		FFSPrint((DBG_ERROR, "FFSv2BlockMap: error input paramters.\n"));

		FFSBreakPoint();

		return 0;
	}	

	/* 流立, 埃立, 2吝 埃立 贸府 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -