📄 create.c
字号:
/*
* 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 + -