📄 create.c
字号:
/*
* COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: create.c
* PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://ext2.yeah.net
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include "ntifs.h"
#include "ext2fs.h"
/* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL gExt2Global;
/* DEFINITIONS *************************************************************/
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, Ext2LookupFileName)
#pragma alloc_text(PAGE, Ext2SearchFcbList)
#pragma alloc_text(PAGE, Ext2ScanDir)
#pragma alloc_text(PAGE, Ext2CreateFile)
#pragma alloc_text(PAGE, Ext2CreateVolume)
#pragma alloc_text(PAGE, Ext2Create)
#pragma alloc_text(PAGE, Ext2CreateInode)
#endif
NTSTATUS
Ext2LookupFileName (IN PEXT2_VCB Vcb,
IN PUNICODE_STRING FullFileName,
IN PEXT2_FCB ParentFcb,
OUT PEXT2_MCB * Ext2Mcb,
IN OUT PEXT2_INODE ext2_inode)
{
NTSTATUS Status;
UNICODE_STRING FileName;
PEXT2_MCB ParentMcb;
PEXT2_MCB Mcb;
EXT2_DIR_ENTRY2 ext2_dir;
int i = 0;
BOOLEAN bRun = TRUE;
BOOLEAN bParent = FALSE;
EXT2_INODE in;
ULONG off = 0;
Status = STATUS_OBJECT_NAME_NOT_FOUND;
*Ext2Mcb = NULL;
if (ParentFcb && FullFileName->Buffer[0] != L'\\')
{
ParentMcb = ParentFcb->Ext2Mcb;
bParent = TRUE;
}
else
{
ParentMcb = Vcb->Ext2McbTree;
}
RtlZeroMemory(&ext2_dir, sizeof(EXT2_DIR_ENTRY2));
if (FullFileName->Length == 0)
{
return Status;
}
if (FullFileName->Length == 2 && FullFileName->Buffer[0] == L'\\')
{
if (!Ext2LoadInode(Vcb, ParentMcb->Inode, ext2_inode))
{
return Status;
}
*Ext2Mcb = Vcb->Ext2McbTree;
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 = Ext2SearchMcb(ParentMcb, &FileName);
if (Mcb)
{
ParentMcb = Mcb;
Status = STATUS_SUCCESS;
if (!IsFlagOn(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
{
if (i < FullFileName->Length/2)
{
Status = STATUS_OBJECT_NAME_NOT_FOUND;
}
break;
}
}
else
{
if (!Ext2LoadInode(Vcb, ParentMcb->Inode, &in))
{
Status = STATUS_OBJECT_NAME_NOT_FOUND;
break;
}
if (!S_ISDIR(in.i_mode))
{
if (i < FullFileName->Length/2)
{
Status = STATUS_OBJECT_NAME_NOT_FOUND;
}
break;
}
Status = Ext2ScanDir (
Vcb,
ParentMcb,
&FileName,
&off,
&in,
&ext2_dir);
if (!NT_SUCCESS(Status))
{
bRun = FALSE;
/*
if (i >= FullFileName->Length/2)
{
*Ext2Mcb = ParentMcb;
}
*/
}
else
{
if (IsFlagOn(Vcb->ext2_super_block->s_feature_incompat, EXT2_FEATURE_INCOMPAT_FILETYPE))
{
if (ext2_dir.file_type == EXT2_FT_DIR)
SetFlag(FileAttr, FILE_ATTRIBUTE_DIRECTORY);
}
else
{
if (!Ext2LoadInode(Vcb, ext2_dir.inode, &in))
{
Status = STATUS_OBJECT_NAME_NOT_FOUND;
break;
}
if (S_ISDIR(in.i_mode))
{
SetFlag(FileAttr, FILE_ATTRIBUTE_DIRECTORY);
}
}
Mcb = Ext2AllocateMcb(Vcb, &FileName, FileAttr);
if (!Mcb)
{
Status = STATUS_OBJECT_NAME_NOT_FOUND;
break;
}
Mcb->Inode = ext2_dir.inode;
Mcb->DeOffset = off;
Ext2AddMcbNode(ParentMcb, Mcb);
ParentMcb = Mcb;
}
}
}
else
{
break;
}
}
if (NT_SUCCESS(Status))
{
*Ext2Mcb = Mcb;
if (ext2_inode)
{
if (!Ext2LoadInode(Vcb, Mcb->Inode, ext2_inode))
{
Ext2DbgPrint(D_CREATE, "Ext2LoopupFileName: error loading Inode %xh\n", Mcb->Inode);
Status = STATUS_INSUFFICIENT_RESOURCES;
}
}
}
return Status;
}
NTSTATUS
Ext2ScanDir (IN PEXT2_VCB Vcb,
IN PEXT2_MCB ParentMcb,
IN PUNICODE_STRING FileName,
IN OUT PULONG Index,
IN PEXT2_INODE ext2_inode,
IN OUT PEXT2_DIR_ENTRY2 ext2_dir)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
USHORT InodeFileNameLength;
UNICODE_STRING InodeFileName;
PEXT2_DIR_ENTRY2 pDir = NULL;
ULONG dwBytes = 0;
BOOLEAN bFound = FALSE;
PEXT2_FCB Dcb = NULL;
LONGLONG Offset = 0;
ULONG inode = ParentMcb->Inode;
ULONG dwRet;
__try
{
pDir = (PEXT2_DIR_ENTRY2) ExAllocatePool(PagedPool,
sizeof(EXT2_DIR_ENTRY2));
if (!pDir)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
InodeFileName.Buffer = ExAllocatePool(
PagedPool,
(EXT2_NAME_LEN + 1) * 2 );
if (!InodeFileName.Buffer)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
Dcb = ParentMcb->Ext2Fcb;
dwBytes = 0;
while (!bFound && dwBytes < ext2_inode->i_size)
{
RtlZeroMemory(pDir, sizeof(EXT2_DIR_ENTRY2));
// Reading the DCB contents
Status = Ext2ReadInode(
NULL,
Vcb,
ext2_inode,
dwBytes,
(PVOID)pDir,
sizeof(EXT2_DIR_ENTRY2),
&dwRet);
if (!NT_SUCCESS(Status))
{
Ext2DbgPrint(D_CREATE, "Ext2ScanDir: Reading Directory Content error.\n");
__leave;
}
if (pDir->inode)
{
InodeFileNameLength = pDir->name_len & 0xff;
InodeFileName.Length = InodeFileName.MaximumLength =
InodeFileNameLength * 2;
RtlZeroMemory(InodeFileName.Buffer, InodeFileNameLength * 2 + 2);
Ext2CharToWchar(
InodeFileName.Buffer,
pDir->name,
InodeFileNameLength );
if (!RtlCompareUnicodeString(
FileName,
&InodeFileName,
TRUE ))
{
bFound = TRUE;
*Index = dwBytes;
RtlCopyMemory(ext2_dir, pDir, pDir->rec_len > sizeof(EXT2_DIR_ENTRY2)
? sizeof(EXT2_DIR_ENTRY2) : pDir->rec_len);
Status = STATUS_SUCCESS;
Ext2DbgPrint(D_CREATE, "Ext2ScanDir: Found: Name=%S Inode=%xh\n", InodeFileName.Buffer, pDir->inode);
}
dwBytes +=pDir->rec_len;
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;
}
/*
PEXT2_FCB
Ext2SearchFcbList( IN PEXT2_VCB Vcb,
IN ULONG inode )
{
BOOLEAN bFound = FALSE;
PLIST_ENTRY Link;
PEXT2_FCB TmpFcb;
Link = Vcb->FcbList.Flink;
while (!bFound && Link != &Vcb->FcbList)
{
TmpFcb = CONTAINING_RECORD(Link, EXT2_FCB, Next);
if (TmpFcb && TmpFcb->Identifier.Type == FCB)
{
#if DBG
Ext2DbgPrint(D_CREATE, "Ext2SearchFcbList: [%s,%xh]\n",
TmpFcb->AnsiFileName.Buffer, TmpFcb->Inode);
#endif
if (TmpFcb->Inode == inode)
{
Ext2DbgPrint(D_CREATE, "Ext2SearchMcb: Found FCB for %xh.\n", inode);
bFound = TRUE;
}
}
Link = Link->Flink;
}
if (bFound)
return TmpFcb;
else
return NULL;
}
*/
NTSTATUS
Ext2CreateFile(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PIO_STACK_LOCATION io_stack;
PEXT2_FCB Fcb = NULL;
PEXT2_FCB pParentFcb = NULL;
BOOLEAN bParentFcbCreated = FALSE;
PEXT2_CCB Ccb = NULL;
PEXT2_INODE ext2_inode;
BOOLEAN VcbResourceAcquired = FALSE;
BOOLEAN bDir = FALSE;
BOOLEAN bFcbAllocated = FALSE;
BOOLEAN bCreated = FALSE;
UNICODE_STRING FileName;
PEXT2_MCB Ext2Mcb = NULL;
PIRP Irp;
ULONG Options;
ULONG CreateDisposition;
BOOLEAN OpenDirectory;
BOOLEAN OpenTargetDirectory;
BOOLEAN CreateDirectory;
BOOLEAN SequentialOnly;
BOOLEAN NoIntermediateBuffering;
BOOLEAN IsPagingFile;
BOOLEAN DirectoryFile;
BOOLEAN NonDirectoryFile;
BOOLEAN NoEaKnowledge;
BOOLEAN DeleteOnClose;
BOOLEAN TemporaryFile;
BOOLEAN CaseSensitive;
ACCESS_MASK DesiredAccess;
ULONG ShareAccess;
Irp = IrpContext->Irp;
io_stack = IoGetCurrentIrpStackLocation(Irp);
Options = io_stack->Parameters.Create.Options;
DirectoryFile = IsFlagOn(Options, FILE_DIRECTORY_FILE);
OpenTargetDirectory = IsFlagOn(io_stack->Flags, SL_OPEN_TARGET_DIRECTORY);
NonDirectoryFile = IsFlagOn(Options, FILE_NON_DIRECTORY_FILE);
SequentialOnly = IsFlagOn(Options, FILE_SEQUENTIAL_ONLY);
NoIntermediateBuffering = IsFlagOn( Options, FILE_NO_INTERMEDIATE_BUFFERING );
NoEaKnowledge = IsFlagOn(Options, FILE_NO_EA_KNOWLEDGE);
DeleteOnClose = IsFlagOn(Options, FILE_DELETE_ON_CLOSE);
CaseSensitive = IsFlagOn(io_stack->Flags, SL_CASE_SENSITIVE);
TemporaryFile = IsFlagOn(io_stack->Parameters.Create.FileAttributes,
FILE_ATTRIBUTE_TEMPORARY );
CreateDisposition = (Options >> 24) & 0x000000ff;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -