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

📄 ext2fs.c

📁 ext2 file system driver for win nt
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * COPYRIGHT:		 See COPYRIGHT.TXT
 * PROJECT:          Ext2 File System for NT
 * FILE:             Ext2fs.c
 * PROGRAMMER:       Matt Wu <mattwu@163.com>
 * HOMEPAGE:		 http://ext2.yeah.net
 * UPDATE HISTORY: 
 */

/* INCLUDES *****************************************************************/

#include "ntifs.h"
#include "ext2fs.h"

/* GLOBALS ***************************************************************/

PEXT2_GLOBAL	Ext2Global = NULL;

/* FUNCTIONS ***************************************************************/

LARGE_INTEGER
Ext2SysTime (IN ULONG i_time)
{
	LARGE_INTEGER SysTime;
	SysTime.QuadPart = (LONGLONG)(i_time) * 10000000;
	SysTime.QuadPart += Ext2Global->TimeZone.QuadPart;
	return SysTime;
}

ULONG
Ext2InodeTime (IN LARGE_INTEGER SysTime)
{
	return (ULONG)((SysTime.QuadPart - Ext2Global->TimeZone.QuadPart) / 10000000);
}


NTSTATUS
Ext2ReadSectors(IN PDEVICE_OBJECT pDeviceObject,
		IN ULONG DiskSector,
		IN ULONG SectorCount,
		IN PVOID Buffer)
{
	LARGE_INTEGER   sectorNumber;
	PIRP            irp;
	IO_STATUS_BLOCK ioStatus;
	KEVENT          event;
	NTSTATUS        Status;
	ULONG           sectorSize;
	
//	KdPrint(("Ext2ReadSectors(pDeviceObject %xh, lba %xh, sectors: %xh Buffer %xh)\n",
//		pDeviceObject,DiskSector, SectorCount, Buffer));
	
	sectorNumber.u.HighPart = 0;
	sectorNumber.u.LowPart = DiskSector * SECTOR_SIZE;
	
	KeInitializeEvent(&event, NotificationEvent, FALSE);
	
	sectorSize = SECTOR_SIZE * SectorCount;
	
	irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
		pDeviceObject,
		Buffer,
		sectorSize,
		&sectorNumber,
		&event,
		&ioStatus );
	
	if (irp == NULL) 
	{
		return STATUS_UNSUCCESSFUL;
	}
	
	Status = IoCallDriver(pDeviceObject, irp);
	
	if (Status == STATUS_PENDING) 
	{
		KeWaitForSingleObject(&event,
			Suspended,
			KernelMode,
			FALSE,
			NULL);
		Status = ioStatus.Status;
	}
	
	if (!NT_SUCCESS(Status)) 
	{
		KdPrint(("Ext2ReadSectors IO failed!!! Error code: %d(%x)\n", Status, Status));
		return Status;
	}
	
	return Status;
}

NTSTATUS
Ext2WriteSectors(IN PDEVICE_OBJECT pDeviceObject,
		 IN ULONG	DiskSector,
		 IN ULONG       SectorCount,
		 IN PVOID	Buffer)
{
	LARGE_INTEGER   sectorNumber;
	PIRP            irp;
	IO_STATUS_BLOCK ioStatus;
	KEVENT          event;
	NTSTATUS        Status;
	ULONG           sectorSize;
	
	KdPrint(("Ext2WriteSectors(pDeviceObject %xh, lba %xh, sectors: %xh Buffer %xh)\n",
		pDeviceObject,DiskSector, SectorCount, Buffer));
	
	sectorNumber.u.HighPart = 0;
	sectorNumber.u.LowPart = DiskSector * SECTOR_SIZE;
	
	KeInitializeEvent(&event, NotificationEvent, FALSE);
	
	sectorSize = SECTOR_SIZE * SectorCount;
	
	irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
		pDeviceObject,
		Buffer,
		sectorSize,
		&sectorNumber,
		&event,
		&ioStatus );
	
	if (irp == NULL)
	{
		KdPrint(("Ext2WriteSectors: WRITE failed!!!\n"));
		return STATUS_UNSUCCESSFUL;
	}
	
	Status = IoCallDriver(pDeviceObject,
		irp);
	
	if (Status == STATUS_PENDING)
	{
		KeWaitForSingleObject(&event,
			Suspended,
			KernelMode,
			FALSE,
			NULL);
		Status = ioStatus.Status;
	}
	
	if (!NT_SUCCESS(Status))
	{
		KdPrint(("Ext2WriteSectors: IO failed!!! Error code: %d(%x)\n", Status, Status));
		return Status;
	}
	
	KdPrint(("Ext2WriteSectors: Block request succeeded.\n"));
	return Status;
}

NTSTATUS
Ext2ReadDisk(IN PDEVICE_OBJECT pDeviceObject,
	     IN ULONG lba,
	     IN ULONG offset,
	     IN ULONG Size,
	     IN PVOID Buffer)
{
	ULONG		Sectors;
	NTSTATUS	Status;
	PUCHAR		Buf;
	ULONG		off = 0;

	if (offset >= SECTOR_SIZE)
		lba += offset / SECTOR_SIZE;
	off = offset % SECTOR_SIZE;
	Sectors = (off + Size + SECTOR_SIZE - 1) / SECTOR_SIZE;

//      KdPrint(("Ext2ReadDisk: lba %xh, offset: %xh size: %xh Sectors:%xh.\n",
//              lba, offset, Size, Sectors));

	Buf = ExAllocatePool(NonPagedPool, Sectors * SECTOR_SIZE);
	if (!Buf)
	{
		KdPrint(("Ext2ReadDisk: no enough memory.\n"));
		return STATUS_UNSUCCESSFUL;
	}

	Status = Ext2ReadSectors(pDeviceObject, lba, Sectors, Buf);

	if (!NT_SUCCESS(Status))
	{
		KdPrint(("Ext2ReadDisk: Read Block Device error.\n"));
                ExFreePool(Buf);
		return Status;
	}

	RtlCopyMemory(Buffer, &Buf[off], Size);

	ExFreePool(Buf);

	return Status;
}


NTSTATUS
Ext2WriteDisk(IN PDEVICE_OBJECT pDeviceObject,
	      IN ULONG	lba,
 	      IN ULONG  offset,
	      IN ULONG  Size,
	      IN PVOID	Buffer)
{
	ULONG		Sectors;
	NTSTATUS	Status;
	PUCHAR		Buf;
	ULONG		off = 0;

	if (offset >= SECTOR_SIZE)
		lba += offset / SECTOR_SIZE;
	off = offset % SECTOR_SIZE;
	Sectors = (off + Size + SECTOR_SIZE - 1) / SECTOR_SIZE;

	Sectors = (off + Size + SECTOR_SIZE - 1) / SECTOR_SIZE;

	Buf = ExAllocatePool(NonPagedPool, Sectors * SECTOR_SIZE);
	if (!Buf)
	{
		KdPrint(("Ext2WriteDisk: no enough memory.\n"));
		return STATUS_UNSUCCESSFUL;
	}

	if (off)
	{
		Ext2ReadSectors(pDeviceObject, lba, 1, Buf);
	}

	if (((off + Size) % SECTOR_SIZE) != 0)
	{
		if ((Sectors != 1) || offset == 0)
			Ext2ReadSectors(pDeviceObject, lba + Sectors - 1, 1, Buf);
	}

	RtlCopyMemory(&Buf[off], Buffer, Size);

	Status = Ext2WriteSectors(pDeviceObject, lba, Sectors, Buf);

	if (!NT_SUCCESS(Status))
	{
		KdPrint(("Ext2WriteDisk: Write Block Device error.\n"));
	}

	ExFreePool(Buf);

	return Status;
}

NTSTATUS 
Ext2DiskIoControl (IN PDEVICE_OBJECT   pDeviceObject,
		   IN ULONG            IoctlCode,
		   IN PVOID            InputBuffer,
		   IN ULONG            InputBufferSize,
		   IN OUT PVOID        OutputBuffer,
		   IN OUT PULONG       OutputBufferSize)
{
	ULONG           OutBufferSize = 0;
	KEVENT          Event;
	PIRP            Irp;
	IO_STATUS_BLOCK IoStatus;
	NTSTATUS        Status;
	
	PAGED_CODE();
	
	ASSERT(pDeviceObject != NULL);
	
	if (OutputBufferSize)
	{
		OutBufferSize = *OutputBufferSize;
	}
	
	KeInitializeEvent(&Event, NotificationEvent, FALSE);
	
	Irp = IoBuildDeviceIoControlRequest(
		IoctlCode,
		pDeviceObject,
		InputBuffer,
		InputBufferSize,
		OutputBuffer,
		OutBufferSize,
		FALSE,
		&Event,
		&IoStatus
		);
	
	if (Irp == NULL)
	{
		KdPrint(("Ext2DiskIoControl: Building IRQ error!\n"));
		return STATUS_INSUFFICIENT_RESOURCES;
	}
	
	Status = IoCallDriver(pDeviceObject, Irp);
	
	if (Status == STATUS_PENDING)
	{
		KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
		Status = IoStatus.Status;
	}
	
	if (OutputBufferSize)
	{
		*OutputBufferSize = IoStatus.Information;
	}
	
	return Status;
}


NTSTATUS
Ext2ReadDiskOverrideVerify (IN PDEVICE_OBJECT pDeviceObject,
			    IN ULONG DiskSector, 
			    IN ULONG SectorCount,
			    IN OUT PUCHAR Buffer)
{
	PIO_STACK_LOCATION  IoStackLocation;
	LARGE_INTEGER sectorNumber;
	PIRP Irp;
	IO_STATUS_BLOCK IoStatus;
	KEVENT event;
	NTSTATUS Status;
	ULONG sectorSize;

	PAGED_CODE();

	sectorNumber.u.LowPart = DiskSector << 9;
	sectorNumber.u.HighPart = DiskSector >> 23;
	
	KeInitializeEvent (&event, NotificationEvent, FALSE);
	sectorSize = SECTOR_SIZE * SectorCount;
	
	Irp = IoBuildSynchronousFsdRequest (IRP_MJ_READ,
		pDeviceObject,
		Buffer,
		sectorSize,
		&sectorNumber, 
		&event, 
		&IoStatus);
	
	if (!Irp)
	{
		KdPrint(("Ext2ReadDiskOverrideVerify: IoBuildSynchronousFsdRequest failed\n"));
		return(STATUS_UNSUCCESSFUL);;
	}

	IoStackLocation = IoGetNextIrpStackLocation(Irp);
	IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
	
	Status = IoCallDriver (pDeviceObject, Irp);
	
	if (Status == STATUS_PENDING)
	{
		KeWaitForSingleObject (&event, Suspended, KernelMode, FALSE, NULL);
		Status = IoStatus.Status;
	}
	
	if (!NT_SUCCESS (Status))
	{
		KdPrint(("Ext2ReadDiskOverrideVerify: IO failed! Error code: %x\n", Status));
		return (Status);
	}

	return (STATUS_SUCCESS);
}


struct ext2_super_block *
Ext2LoadSuper(IN PDEVICE_OBJECT pDeviceObject)
{
	PVOID		Buffer;
	NTSTATUS	Status;
	
	Buffer = ExAllocatePool(NonPagedPool, 2 * SECTOR_SIZE);
	if (!Buffer)
	{
		KdPrint(("Ext2LoadSuper: no enough memory.\n"));
		return NULL;
	}

        Status = Ext2ReadDisk(pDeviceObject, 2, 0, SECTOR_SIZE * 2, Buffer);
	if (!NT_SUCCESS(Status))
	{
		KdPrint(("Ext2ReadDisk: Read Block Device error.\n"));
                ExFreePool(Buffer);
		return NULL;
	}

	return (struct ext2_super_block *)Buffer;
}

NTSTATUS
Ext2SaveSuper(IN PDEVICE_OBJECT pDeviceObject,
	      IN struct ext2_super_block * sb)
{
        return Ext2WriteDisk(pDeviceObject, 2, 0, SECTOR_SIZE * 2, (PVOID)sb);
}

struct ext2_group_desc *
Ext2LoadGroup(IN PEXT2_VCB vcb)
{
	ULONG		size;
	ULONG		lba;
	PVOID		Buffer;
	NTSTATUS	Status;
	PDEVICE_OBJECT pDeviceObject = vcb->TargetDeviceObject;
	struct ext2_super_block * sb = vcb->ext2_super_block;

	vcb->ext2_block = EXT2_MIN_BLOCK << sb->s_log_block_size;
	vcb->ext2_frag = EXT2_MIN_FRAG << sb->s_log_frag_size;

	vcb->ext2_groups = (sb->s_blocks_count - sb->s_first_data_block +
		sb->s_blocks_per_group - 1) / sb->s_blocks_per_group;

	size = sizeof(struct ext2_group_desc) * vcb->ext2_groups;

	Buffer = ExAllocatePool(NonPagedPool, size);
	if (!Buffer)
	{
		KdPrint(("Ext2LoadSuper: no enough memory.\n"));
		return NULL;
	}

	if (vcb->ext2_block == EXT2_MIN_BLOCK)
	{
		lba = 2 * (vcb->ext2_block / SECTOR_SIZE);
	}

	if (vcb->ext2_block > EXT2_MIN_BLOCK)
	{
		lba = vcb->ext2_block / SECTOR_SIZE;
	}

	Status = Ext2ReadDisk(pDeviceObject, lba, 0, size, Buffer);
	if (!NT_SUCCESS(Status))
	{
		KdPrint(("Ext2LoadGroup: Read Block Device error.\n"));
		ExFreePool(Buffer);
		return NULL;
	}

	return (struct ext2_group_desc *)Buffer;
}

NTSTATUS
Ext2SaveGroup(IN PEXT2_VCB vcb,
	      IN struct ext2_group_desc * gd)
{
	ULONG		lba;
	ULONG		size;
	PDEVICE_OBJECT pDeviceObject = vcb->TargetDeviceObject;

	size = vcb->ext2_groups * sizeof(struct ext2_group_desc);

	if (vcb->ext2_block == EXT2_MIN_BLOCK)
	{
		lba = 2 * (vcb->ext2_block / SECTOR_SIZE);
	}

	if (vcb->ext2_block > EXT2_MIN_BLOCK)
	{
		lba = vcb->ext2_block / SECTOR_SIZE;
	}

	return 	Ext2WriteDisk(pDeviceObject, lba, 0, size, (PVOID)gd);

}

BOOLEAN
Ext2GetInodeLba (IN PEXT2_VCB	vcb,
		 IN ULONG	inode,
		 OUT PULONG	lba,
		 OUT PULONG	offset)
{
	ULONG loc;

	if (inode < 1 || inode > vcb->ext2_super_block->s_inodes_count)
	{
		KdPrint(("Ext2GetInodeLba: Inode value %xh is invalid.\n",inode));
		*lba = 0;
		*offset = 0;
		return FALSE;
	}

	loc = vcb->ext2_group_desc[(inode - 1) / vcb->ext2_super_block->s_inodes_per_group].bg_inode_table * vcb->ext2_block +
		((inode - 1) % vcb->ext2_super_block->s_inodes_per_group) * sizeof(struct ext2_inode);
	*lba = loc / SECTOR_SIZE;
	*offset = loc % SECTOR_SIZE;

//	KdPrint(("Ext2GetInodeLba: inode=%xh lba=%xh offset=%xh\n",
//		inode, *lba, *offset));
	return TRUE;
}

BOOLEAN
Ext2LoadInode (IN PEXT2_VCB	vcb,
	       IN ULONG		inode,
	       IN struct ext2_inode *ext2_inode)
{
	ULONG		lba;
	ULONG		offset;
	NTSTATUS	Status;

	if (!Ext2GetInodeLba(vcb, inode, &lba, &offset))
	{
		KdPrint(("Ext2LoadInode: error get inode(%xh)'s addr.\n", inode));
		return FALSE;
	}

	Status = Ext2ReadDisk(vcb->TargetDeviceObject,
		lba,
		offset,
		sizeof(EXT2_INODE),
		(PVOID)ext2_inode);

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

	return TRUE;
}

BOOLEAN
Ext2SaveInode (IN PEXT2_VCB vcb,
	       IN ULONG inode,
	       IN struct ext2_inode *ext2_inode)
{
	ULONG		lba;
	ULONG		offset;
	NTSTATUS	Status;

	if (!Ext2GetInodeLba(vcb, inode, &lba, &offset))
	{
		KdPrint(("Ext2LoadInode: error get inode(%xh)'s addr.\n", inode));
		return FALSE;
	}

	Status = Ext2WriteDisk(vcb->TargetDeviceObject,
		lba,
		offset,
		sizeof(EXT2_INODE),
		(PVOID)ext2_inode);

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

	return TRUE;
}

ULONG Ext2GetBlock(IN PEXT2_VCB vcb,
		   ULONG dwContent,
		   ULONG Index,
		   int layer )
{
	ULONG *pData = NULL;
	ULONG lba = 0;
	ULONG i = 0, j = 0, temp = 1;
	ULONG dwBlk = 0;

	lba = dwContent * vcb->ext2_block / SECTOR_SIZE;

	if (layer == 0)
	{
		dwBlk = dwContent;
	}
	else if (layer <= 3)
	{
		pData = (ULONG *)ExAllocatePool(NonPagedPool,
					vcb->ext2_block);
		if (!pData)
		{
			KdPrint(("Ext2GetBlock: no enough memory.\n"));
			return dwBlk;
		}

		Ext2ReadDisk(vcb->TargetDeviceObject, lba, 0, vcb->ext2_block, (PVOID)pData);

		for (i=0; i<(ULONG)(layer - 1); i++)
		{
			temp *= (vcb->ext2_block/4);
		}

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

		dwBlk = Ext2GetBlock(vcb, pData[i], j, layer - 1);

		ExFreePool(pData);
	}
	
	return dwBlk;
}

ULONG Ext2BlockMap(IN PEXT2_VCB vcb,
		   IN struct ext2_inode* ext2_inode,
		   IN ULONG Index)
{
	ULONG dwSizes[3] = {vcb->ext2_block / 4, 0, 0};
	int   i;

	if (Index >= ext2_inode->i_blocks)
	{
		KdPrint(("Ext2BlockMap: error input paramters.\n"));
		return 0;
	}

	if (Index < 12)
	{
		return ext2_inode->i_block[Index];
	}

⌨️ 快捷键说明

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