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

📄 create.c

📁 FSD file system driver
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 
 * FFS File System Driver for Windows
 *
 * create.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, FFSv1LookupFileName)
#pragma alloc_text(PAGE, FFSv2LookupFileName)
#pragma alloc_text(PAGE, FFSSearchFcbList)
#pragma alloc_text(PAGE, FFSv1ScanDir)
#pragma alloc_text(PAGE, FFSv2ScanDir)
#pragma alloc_text(PAGE, FFSCreateFile)
#pragma alloc_text(PAGE, FFSCreateVolume)
#pragma alloc_text(PAGE, FFSCreate)
#pragma alloc_text(PAGE, FFSCreateInode)
#pragma alloc_text(PAGE, FFSSupersedeOrOverWriteFile)
#endif


NTSTATUS
FFSv1LookupFileName(
	IN PFFS_VCB            Vcb,
	IN PUNICODE_STRING     FullFileName,
	IN PFFS_MCB            ParentMcb,
	OUT PFFS_MCB*          FFSMcb,
	IN OUT PFFSv1_INODE    dinode1)
{
	NTSTATUS        Status;
	UNICODE_STRING  FileName;
	PFFS_MCB        Mcb;

	FFS_DIR_ENTRY   ffs_dir;
	int             i = 0;
	BOOLEAN         bRun = TRUE;
	BOOLEAN         bParent = FALSE;
	FFSv1_INODE     in;
	ULONG           off = 0;

	Status = STATUS_OBJECT_NAME_NOT_FOUND;

	*FFSMcb = NULL;

	if (ParentMcb)
	{
		bParent = TRUE;
	}
	else if (FullFileName->Buffer[0] == L'\\')
	{
		ParentMcb = Vcb->McbTree;
	}
	else
	{
		return STATUS_OBJECT_PATH_NOT_FOUND;
	}

	RtlZeroMemory(&ffs_dir, sizeof(FFS_DIR_ENTRY));

	if (FullFileName->Length == 0)
	{
		return Status;
	}

	if (FullFileName->Length == 2 && FullFileName->Buffer[0] == L'\\')
	{
		if (!FFSv1LoadInode(Vcb, ParentMcb->Inode, dinode1))
		{
			return Status;      
		}

		*FFSMcb = Vcb->McbTree;

		return STATUS_SUCCESS;
	}

	while (bRun && i < FullFileName->Length / 2)
	{
		int Length;
		ULONG FileAttr = FILE_ATTRIBUTE_NORMAL;

		if (bParent)
		{
			bParent = FALSE;
		}
		else
		{
			while(i < FullFileName->Length / 2 && FullFileName->Buffer[i] == L'\\') i++;
		}

		Length = i;

		while(i < FullFileName->Length / 2 && (FullFileName->Buffer[i] != L'\\')) i++;

		if (i - Length > 0)
		{
			FileName = *FullFileName;
			FileName.Buffer += Length;
			FileName.Length = (USHORT)((i - Length) * 2);

			Mcb = FFSSearchMcb(Vcb, ParentMcb, &FileName);

			if (Mcb)
			{
				ParentMcb = Mcb;

				Status = STATUS_SUCCESS;

				if (!IsFlagOn(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
				{
					if (i < FullFileName->Length / 2)
					{
						Status = STATUS_OBJECT_PATH_NOT_FOUND;
					}

					break;
				}
			}
			else
			{
				if (!FFSv1LoadInode(Vcb, ParentMcb->Inode, &in))
				{
					Status = STATUS_OBJECT_NAME_NOT_FOUND;
					break;
				}

				if ((in.di_mode & IFMT) != IFDIR)
				{
					if (i < FullFileName->Length / 2)
					{
						Status =  STATUS_OBJECT_NAME_NOT_FOUND;
					}
					break;
				}

				Status = FFSv1ScanDir(
						Vcb,
						ParentMcb,
						&FileName,
						&off,
						&in,
						&ffs_dir);

				if (!NT_SUCCESS(Status))
				{
					bRun = FALSE;
					/*
					   if (i >= FullFileName->Length/2)
					   {
					 *FFSMcb = ParentMcb;
					 }
					 */
				}
				else
				{
#if 0
					if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, 
								FFS_FEATURE_INCOMPAT_FILETYPE))
					{
						if (ffs_dir.d_type == FFS_FT_DIR)
							SetFlag(FileAttr, FILE_ATTRIBUTE_DIRECTORY);
					}
					else
#endif
					{
						if (!FFSv1LoadInode(Vcb, ffs_dir.d_ino, &in))
						{
							Status = STATUS_OBJECT_NAME_NOT_FOUND;
							break;
						}

						if ((in.di_mode & IFMT) == IFDIR)
						{
							SetFlag(FileAttr, FILE_ATTRIBUTE_DIRECTORY);
						}
					}

					SetFlag(ParentMcb->Flags, MCB_IN_USE);
					Mcb = FFSAllocateMcb(Vcb, &FileName, FileAttr);
					ClearFlag(ParentMcb->Flags, MCB_IN_USE);

					if (!Mcb)
					{
						Status = STATUS_OBJECT_NAME_NOT_FOUND;
						break;
					}

					Mcb->Inode = ffs_dir.d_ino;
					Mcb->DeOffset = off;
					FFSAddMcbNode(Vcb, ParentMcb, Mcb);
					ParentMcb = Mcb;
				}
			}
		}
		else
		{
			break;
		}
	}

	if (NT_SUCCESS(Status))
	{
		*FFSMcb = Mcb;
		if (dinode1)
		{
			if (!FFSv1LoadInode(Vcb, Mcb->Inode, dinode1))
			{
				FFSPrint((DBG_ERROR, "FFSv1LookupFileName: error loading Inode %xh\n",
							Mcb->Inode));
				Status = STATUS_INSUFFICIENT_RESOURCES;
			}
		}
	}

	return Status;
}


NTSTATUS
FFSv2LookupFileName(
	IN PFFS_VCB            Vcb,
	IN PUNICODE_STRING     FullFileName,
	IN PFFS_MCB            ParentMcb,
	OUT PFFS_MCB*          FFSMcb,
	IN OUT PFFSv2_INODE    dinode2)
{
	NTSTATUS        Status;
	UNICODE_STRING  FileName;
	PFFS_MCB        Mcb;

	FFS_DIR_ENTRY   ffs_dir;
	int             i = 0;
	BOOLEAN         bRun = TRUE;
	BOOLEAN         bParent = FALSE;
	FFSv2_INODE     in;
	ULONG           off = 0;

	Status = STATUS_OBJECT_NAME_NOT_FOUND;

	*FFSMcb = NULL;

	if (ParentMcb)
	{
		bParent = TRUE;
	}
	else if (FullFileName->Buffer[0] == L'\\')
	{
		ParentMcb = Vcb->McbTree;
	}
	else
	{
		return STATUS_OBJECT_PATH_NOT_FOUND;
	}

	RtlZeroMemory(&ffs_dir, sizeof(FFS_DIR_ENTRY));

	if (FullFileName->Length == 0)
	{
		return Status;
	}

	if (FullFileName->Length == 2 && FullFileName->Buffer[0] == L'\\')
	{
		if (!FFSv2LoadInode(Vcb, ParentMcb->Inode, dinode2))
		{
			return Status;      
		}

		*FFSMcb = Vcb->McbTree;

		return STATUS_SUCCESS;
	}

	while (bRun && i < FullFileName->Length / 2)
	{
		int Length;
		ULONG FileAttr = FILE_ATTRIBUTE_NORMAL;

		if (bParent)
		{
			bParent = FALSE;
		}
		else
		{
			while(i < FullFileName->Length / 2 && FullFileName->Buffer[i] == L'\\') i++;
		}

		Length = i;

		while(i < FullFileName->Length / 2 && (FullFileName->Buffer[i] != L'\\')) i++;

		if (i - Length > 0)
		{
			FileName = *FullFileName;
			FileName.Buffer += Length;
			FileName.Length = (USHORT)((i - Length) * 2);

			Mcb = FFSSearchMcb(Vcb, ParentMcb, &FileName);

			if (Mcb)
			{
				ParentMcb = Mcb;

				Status = STATUS_SUCCESS;

				if (!IsFlagOn(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
				{
					if (i < FullFileName->Length / 2)
					{
						Status = STATUS_OBJECT_PATH_NOT_FOUND;
					}

					break;
				}
			}
			else
			{
				if (!FFSv2LoadInode(Vcb, ParentMcb->Inode, &in))
				{
					Status = STATUS_OBJECT_NAME_NOT_FOUND;
					break;
				}

				if ((in.di_mode & IFMT) != IFDIR)
				{
					if (i < FullFileName->Length / 2)
					{
						Status =  STATUS_OBJECT_NAME_NOT_FOUND;
					}
					break;
				}

				Status = FFSv2ScanDir(
						Vcb,
						ParentMcb,
						&FileName,
						&off,
						&in,
						&ffs_dir);

				if (!NT_SUCCESS(Status))
				{
					bRun = FALSE;
					/*
					   if (i >= FullFileName->Length/2)
					   {
					 *FFSMcb = ParentMcb;
					 }
					 */
				}
				else
				{
#if 0
					if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, 
								FFS_FEATURE_INCOMPAT_FILETYPE))
					{
						if (ffs_dir.d_type == FFS_FT_DIR)
							SetFlag(FileAttr, FILE_ATTRIBUTE_DIRECTORY);
					}
					else
#endif
					{
						if (!FFSv2LoadInode(Vcb, ffs_dir.d_ino, &in))
						{
							Status = STATUS_OBJECT_NAME_NOT_FOUND;
							break;
						}

						if ((in.di_mode & IFMT) == IFDIR)
						{
							SetFlag(FileAttr, FILE_ATTRIBUTE_DIRECTORY);
						}
					}

					SetFlag(ParentMcb->Flags, MCB_IN_USE);
					Mcb = FFSAllocateMcb(Vcb, &FileName, FileAttr);
					ClearFlag(ParentMcb->Flags, MCB_IN_USE);

					if (!Mcb)
					{
						Status = STATUS_OBJECT_NAME_NOT_FOUND;
						break;
					}

					Mcb->Inode = ffs_dir.d_ino;
					Mcb->DeOffset = off;
					FFSAddMcbNode(Vcb, ParentMcb, Mcb);
					ParentMcb = Mcb;
				}
			}
		}
		else
		{
			break;
		}
	}

	if (NT_SUCCESS(Status))
	{
		*FFSMcb = Mcb;
		if (dinode2)
		{
			if (!FFSv2LoadInode(Vcb, Mcb->Inode, dinode2))
			{
				FFSPrint((DBG_ERROR, "FFSv2LookupFileName: error loading Inode %xh\n",
							Mcb->Inode));
				Status = STATUS_INSUFFICIENT_RESOURCES;
			}
		}
	}

	return Status;
}


NTSTATUS
FFSv1ScanDir(
	IN PFFS_VCB            Vcb,
	IN PFFS_MCB            ParentMcb,
	IN PUNICODE_STRING     FileName,
	IN OUT PULONG          Index,
	IN PFFSv1_INODE        dinode1,
	IN OUT PFFS_DIR_ENTRY  ffs_dir)
{
	NTSTATUS                Status = STATUS_UNSUCCESSFUL;
	USHORT                  InodeFileNameLength;
	UNICODE_STRING          InodeFileName;

	PFFS_DIR_ENTRY          pDir = NULL;
	ULONG                   dwBytes = 0;
	BOOLEAN                 bFound = FALSE;
	LONGLONG                Offset = 0;
	ULONG                   inode = ParentMcb->Inode;

	ULONG                   dwRet;

	__try
	{

		pDir = (PFFS_DIR_ENTRY)ExAllocatePool(PagedPool,
				sizeof(FFS_DIR_ENTRY));
		if (!pDir)
		{
			Status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}

		InodeFileName.Buffer = ExAllocatePool(
				PagedPool,
				(FFS_NAME_LEN + 1) * 2);

		if (!InodeFileName.Buffer)
		{
			Status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}

		dwBytes = 0;

		while (!bFound && dwBytes < dinode1->di_size)
		{
			RtlZeroMemory(pDir, sizeof(FFS_DIR_ENTRY));

			// Reading the DCB contents
			Status = FFSv1ReadInode(
					NULL,
					Vcb,
					dinode1,
					dwBytes,
					(PVOID)pDir,
					sizeof(FFS_DIR_ENTRY),
					&dwRet);


			if (!NT_SUCCESS(Status))
			{
				FFSPrint((DBG_ERROR, "FFSv1ScanDir: Reading Directory Content error.\n"));
				__leave;
			}

			if (pDir->d_ino /*&& (pDir->d_ino < INODES_COUNT)*/)
			{
				OEM_STRING OemName;
				OemName.Buffer = pDir->d_name;
				OemName.Length = (pDir->d_namlen & 0xff);
				OemName.MaximumLength = OemName.Length;

				InodeFileNameLength = (USHORT)
					RtlOemStringToCountedUnicodeSize(&OemName);

				InodeFileName.Length = 0;
				InodeFileName.MaximumLength = (FFS_NAME_LEN + 1) * 2;

				RtlZeroMemory(InodeFileName.Buffer,
						InodeFileNameLength + 2);

				Status = FFSOEMToUnicode(
						&InodeFileName,
						&OemName);

				if (!NT_SUCCESS(Status))
				{
					__leave;
				}

				if (!RtlCompareUnicodeString(
							FileName,
							&InodeFileName,
							TRUE))
				{
					bFound = TRUE;
					*Index = dwBytes;
					RtlCopyMemory(ffs_dir, pDir, pDir->d_reclen > sizeof(FFS_DIR_ENTRY)
							? sizeof(FFS_DIR_ENTRY) : pDir->d_reclen);
					Status = STATUS_SUCCESS;

					FFSPrint((DBG_INFO, "FFSv1ScanDir: Found: Name=%S Inode=%xh\n", InodeFileName.Buffer, pDir->d_ino));
				}

				dwBytes +=pDir->d_reclen;
				Offset = (LONGLONG)dwBytes;
			}
			else
			{
				if (pDir->d_ino == 0)
				{
					if (pDir->d_reclen == 0)
					{
						FFSBreakPoint();
						break;
					}
					else
					{
						dwBytes +=pDir->d_reclen;
						Offset = (LONGLONG)dwBytes;
					}
				}
				else
				{
					break;
				}
			}
		}

		if (!bFound)
		{
			Status = STATUS_NO_SUCH_FILE;
		}
	}

	__finally
	{
		if (InodeFileName.Buffer != NULL)
		{
			ExFreePool(InodeFileName.Buffer);
		}

		if (pDir)
			ExFreePool(pDir);
	}

	return Status;
}


NTSTATUS
FFSv2ScanDir(
	IN PFFS_VCB            Vcb,
	IN PFFS_MCB            ParentMcb,
	IN PUNICODE_STRING     FileName,
	IN OUT PULONG          Index,
	IN PFFSv2_INODE        dinode2,
	IN OUT PFFS_DIR_ENTRY  ffs_dir)
{
	NTSTATUS                Status = STATUS_UNSUCCESSFUL;
	USHORT                  InodeFileNameLength;
	UNICODE_STRING          InodeFileName;

	PFFS_DIR_ENTRY          pDir = NULL;
	ULONG                   dwBytes = 0;
	BOOLEAN                 bFound = FALSE;
	LONGLONG                Offset = 0;
	ULONG                   inode = ParentMcb->Inode;

	ULONG                   dwRet;

	__try
	{

		pDir = (PFFS_DIR_ENTRY)ExAllocatePool(PagedPool,
				sizeof(FFS_DIR_ENTRY));
		if (!pDir)
		{
			Status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}

		InodeFileName.Buffer = ExAllocatePool(
				PagedPool,
				(FFS_NAME_LEN + 1) * 2);

		if (!InodeFileName.Buffer)
		{
			Status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}

		dwBytes = 0;

		while (!bFound && dwBytes < dinode2->di_size)
		{
			RtlZeroMemory(pDir, sizeof(FFS_DIR_ENTRY));

			// Reading the DCB contents
			Status = FFSv2ReadInode(
					NULL,
					Vcb,
					dinode2,
					dwBytes,
					(PVOID)pDir,
					sizeof(FFS_DIR_ENTRY),
					&dwRet);


			if (!NT_SUCCESS(Status))
			{
				FFSPrint((DBG_ERROR, "FFSv2ScanDir: Reading Directory Content error.\n"));
				__leave;
			}

			if (pDir->d_ino /*&& (pDir->d_ino < INODES_COUNT)*/)
			{
				OEM_STRING OemName;
				OemName.Buffer = pDir->d_name;
				OemName.Length = (pDir->d_namlen & 0xff);
				OemName.MaximumLength = OemName.Length;

				InodeFileNameLength = (USHORT)
					RtlOemStringToCountedUnicodeSize(&OemName);

				InodeFileName.Length = 0;
				InodeFileName.MaximumLength = (FFS_NAME_LEN + 1) * 2;

				RtlZeroMemory(InodeFileName.Buffer,
						InodeFileNameLength + 2);

				Status = FFSOEMToUnicode(
						&InodeFileName,
						&OemName);

				if (!NT_SUCCESS(Status))
				{
					__leave;
				}

				if (!RtlCompareUnicodeString(
							FileName,

⌨️ 快捷键说明

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