📄 ext2fs.c
字号:
if (Fcb->Identifier.Type == VCB)
{
if (Vcb->Flags & VCB_VOLUME_LOCKED)
{
Vcb->Flags &= ~VCB_VOLUME_LOCKED;
Ext2ClearVpbFlag(Vcb->Vpb, VPB_LOCKED);
}
Vcb->ReferenceCount--;
if (!Vcb->ReferenceCount && Vcb->Flags & VCB_DISMOUNT_PENDING)
{
FreeVcb = TRUE;
}
Status = STATUS_SUCCESS;
__leave;
}
ASSERT((Fcb->Identifier.Type == FCB) &&
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
#ifndef EXT2_RO
if (!Fcb->IsPageFile)
#endif
{
if (!ExAcquireResourceExclusiveLite(
&Fcb->MainResource,
IrpContext->IsSynchronous ))
{
Status = STATUS_PENDING;
__leave;
}
FcbResourceAcquired = TRUE;
}
Ccb = (PEXT2_CCB) FileObject->FsContext2;
ASSERT(Ccb != NULL);
ASSERT((Ccb->Identifier.Type == CCB) &&
(Ccb->Identifier.Size == sizeof(EXT2_CCB)));
Fcb->ReferenceCount--;
Vcb->ReferenceCount--;
if (!Vcb->ReferenceCount && Vcb->Flags & VCB_DISMOUNT_PENDING)
{
FreeVcb = TRUE;
}
Ext2FreeCcb(Ccb);
if (!Fcb->ReferenceCount)
{
ExReleaseResourceForThreadLite(
&Fcb->MainResource,
ExGetCurrentResourceThread() );
FcbResourceAcquired = FALSE;
Ext2FreeFcb(Fcb);
}
Status = STATUS_SUCCESS;
}
__finally
{
if (VcbResourceAcquired)
{
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread() );
}
if (FcbResourceAcquired)
{
ExReleaseResourceForThreadLite(
&Fcb->MainResource,
ExGetCurrentResourceThread() );
}
if (!IrpContext->ExceptionInProgress)
{
if (Status == STATUS_PENDING)
{
Status = STATUS_SUCCESS;
if (IrpContext->Irp != NULL)
{
IrpContext->Irp->IoStatus.Status = Status;
Ext2CompleteRequest(
IrpContext->Irp,
(CCHAR)
(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT)
);
IrpContext->Irp = NULL;
}
Ext2QueueCloseRequest(IrpContext);
}
else
{
if (IrpContext->Irp != NULL)
{
IrpContext->Irp->IoStatus.Status = Status;
Ext2CompleteRequest(
IrpContext->Irp,
(CCHAR)
(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT)
);
}
Ext2FreeIrpContext(IrpContext);
if (FreeVcb)
{
Ext2FreeVcb(Vcb);
}
}
}
}
return Status;
}
VOID
Ext2QueueCloseRequest (IN PEXT2_IRP_CONTEXT IrpContext)
{
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
// IsSynchronous means we can block (so we don't requeue it)
IrpContext->IsSynchronous = TRUE;
ExInitializeWorkItem(
&IrpContext->WorkQueueItem,
Ext2DeQueueCloseRequest,
IrpContext);
ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
}
VOID
Ext2DeQueueCloseRequest (IN PVOID Context)
{
PEXT2_IRP_CONTEXT IrpContext;
IrpContext = (PEXT2_IRP_CONTEXT) Context;
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
__try
{
__try
{
FsRtlEnterFileSystem();
Ext2Close(IrpContext);
}
__except (Ext2ExceptionFilter(IrpContext, GetExceptionCode()))
{
Ext2ExceptionHandler(IrpContext);
}
}
__finally
{
FsRtlExitFileSystem();
}
}
NTSTATUS
Ext2LookupFileName (IN PEXT2_VCB Vcb,
IN PUNICODE_STRING FullFileName,
IN OUT PULONG Offset,
IN OUT PULONG Inode,
IN OUT PULONG DirInode,
IN OUT PEXT2_INODE ext2_inode)
{
ULONG RootInode = 2;
UNICODE_STRING FileName;
NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND;
EXT2_DIR_ENTRY ext2_dir;
USHORT i = 0;
BOOLEAN bRun = TRUE;
BOOLEAN bCurrent = FALSE;
EXT2_INODE in;
ULONG off = 0;
*Offset = 0;
*Inode = 0;
if (*DirInode != 0 && FullFileName->Buffer[0] != L'\\')
{
bCurrent = TRUE;
RootInode = *DirInode;
}
else
{
RootInode = 2;
*DirInode = 2;
}
RtlZeroMemory(&ext2_dir, sizeof(EXT2_DIR_ENTRY));
if (FullFileName->Length == 0)
{
return Status;
}
if (FullFileName->Length == 2 && FullFileName->Buffer[0] == L'\\')
{
if (!Ext2LoadInode(Vcb, RootInode, ext2_inode))
{
return Status;
}
*Inode = 2;
*DirInode = 2;
return STATUS_SUCCESS;
}
while (bRun && i < FullFileName->Length/2)
{
ULONG Length;
if (bCurrent)
{
bCurrent = FALSE;
}
else
{
if(FullFileName->Buffer[i++] != L'\\')
break;
}
Length = i;
while(i < FullFileName->Length/2 && (FullFileName->Buffer[i] != L'\\'))
i++;
if (i - Length >0)
{
if (NT_SUCCESS(Status))
RootInode = ext2_dir.inode;
FileName = *FullFileName;
FileName.Buffer += Length;
FileName.Length = (USHORT)((i - Length) * 2);
if (!Ext2LoadInode(Vcb, RootInode, &in))
{
return STATUS_OBJECT_NAME_NOT_FOUND;
}
if (!S_ISDIR(in.i_mode))
break;
Status = Ext2ScanDir (
Vcb,
RootInode,
&FileName,
&off,
&in,
&ext2_dir);
if (!NT_SUCCESS(Status))
bRun = FALSE;
}
}
if (NT_SUCCESS(Status))
{
if (Inode)
*Inode = ext2_dir.inode;
if (DirInode)
*DirInode = RootInode;
if (Offset)
*Offset = 0;
if (ext2_inode)
Ext2LoadInode(Vcb, ext2_dir.inode, ext2_inode);
}
return Status;
}
NTSTATUS
Ext2ScanDir (IN PEXT2_VCB Vcb,
IN ULONG inode,
IN PUNICODE_STRING FileName,
IN OUT PULONG Index,
IN PEXT2_INODE ext2_inode,
IN OUT PEXT2_DIR_ENTRY ext2_dir)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
USHORT InodeFileNameLength;
UNICODE_STRING InodeFileName;
PVOID DirectoryContent = NULL;
struct ext2_dir_entry* pDir = NULL;
ULONG dwBytes;
BOOLEAN bFound = FALSE;
InodeFileName.Buffer = NULL;
__try
{
DirectoryContent = ExAllocatePool(NonPagedPool,
ext2_inode->i_size);
if (!DirectoryContent)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
Ext2ReadInode(Vcb, ext2_inode, 0, DirectoryContent, ext2_inode->i_size);
dwBytes = 0;
pDir = (struct ext2_dir_entry *) ((PUCHAR)DirectoryContent + dwBytes);
while (!bFound && dwBytes < ext2_inode->i_size && pDir->inode)
{
InodeFileNameLength = pDir->name_len & 0xff;
InodeFileName.Length = InodeFileName.MaximumLength =
InodeFileNameLength * 2;
InodeFileName.Buffer = ExAllocatePool(
NonPagedPool,
InodeFileNameLength * 2 + 2);
RtlZeroMemory(InodeFileName.Buffer, InodeFileNameLength * 2 + 2);
Ext2CharToWchar(
InodeFileName.Buffer,
pDir->name,
InodeFileNameLength );
KdPrint(("Ext2ScanDir: file:%S to comp.\n", InodeFileName.Buffer));
if (!RtlCompareUnicodeString(
FileName,
&InodeFileName,
TRUE ))
{
bFound = TRUE;
*Index = dwBytes;
RtlCopyMemory(ext2_dir, pDir, pDir->rec_len > sizeof(EXT2_DIR_ENTRY)
? sizeof(EXT2_DIR_ENTRY) : pDir->rec_len);
Status = STATUS_SUCCESS;
KdPrint(("Ext2ScanDir: Found: inode=%xh\n", pDir->inode));
}
if (InodeFileName.Buffer != NULL)
{
ExFreePool(InodeFileName.Buffer);
InodeFileName.Buffer = NULL;
}
dwBytes +=pDir->rec_len;
pDir = (struct ext2_dir_entry *) ((PUCHAR)DirectoryContent + dwBytes);
}
if (!bFound)
Status = STATUS_NO_SUCH_FILE;
}
__finally
{
if (InodeFileName.Buffer != NULL)
{
ExFreePool(InodeFileName.Buffer);
}
if (DirectoryContent)
ExFreePool(DirectoryContent);
}
return Status;
}
NTSTATUS
Ext2OpenFile(PEXT2_VCB Vcb, PIRP Irp)
{
NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND;
PIO_STACK_LOCATION io_stack;
PEXT2_FCB Fcb = NULL;
PEXT2_FCB pParentFcb = NULL;
PEXT2_CCB Ccb = NULL;
ULONG found_index = 0;
struct ext2_inode* ext2_inode;
PLIST_ENTRY Link;
PEXT2_FCB TmpFcb;
BOOLEAN VcbResourceAcquired = FALSE;
BOOLEAN bFound = FALSE;
BOOLEAN bDir = FALSE;
ULONG inode, dir_inode;
UNICODE_STRING FileName;
FileName.Buffer = NULL;
io_stack = IoGetCurrentIrpStackLocation(Irp);
__try
{
ExAcquireResourceExclusiveLite(
&Vcb->MainResource,
TRUE );
VcbResourceAcquired = TRUE;
ext2_inode = ExAllocatePool(
NonPagedPool,
sizeof(struct ext2_inode) );
if (!ext2_inode)
__leave;
FileName.MaximumLength = 0x400;
if (io_stack->FileObject->RelatedFileObject)
{
pParentFcb = (PEXT2_FCB)(io_stack->FileObject->RelatedFileObject->FsContext);
}
FileName = io_stack->FileObject->FileName;
if (pParentFcb)
{
dir_inode = pParentFcb->inode;
}
else
{
dir_inode = 2;
}
KdPrint(("Ext2OpenFile: %S Opt: %xh.\n",
FileName.Buffer,
io_stack->Parameters.Create.Options));
Status = Ext2LookupFileName(
Vcb,
&FileName,
&found_index,
&inode,
&dir_inode,
ext2_inode );
if (!NT_SUCCESS(Status))
{
__leave;
}
/*
else
{
bDir = (io_stack->FileObject->Flags & 0x02) ? TRUE : FALSE;
if (io_stack->FileObject->FileName.Buffer[0] == L'\\' &&
io_stack->FileObject->FileName.Length == 2 &&
Vcb->inode != 0 )
bDir = FALSE;
if (S_ISDIR(ext2_inode->i_mode) && (Vcb->inode != inode) && bDir)
{
Vcb->inode = inode;
if (Vcb->Name.Buffer)
ExFreePool(Vcb->Name.Buffer);
Vcb->Name.Buffer = ExAllocatePool(NonPagedPool, Length + 2);
RtlZeroMemory(Vcb->Name.Buffer, Length + 2);
Vcb->Name.MaximumLength = 0x400;
Vcb->Name.Length = 0;
RtlAppendUnicodeStringToString(
&(Vcb->Name), &FileName);
if (Vcb->Name.Buffer[(Length - 2)/2] != L'\\')
{
Vcb->Name.Buffer[Length/2] = L'\\';
Vcb->Name.Length +=2;
}
}
else
{
// Vcb->inode = dir_inode;
}
}
*/
Link = Vcb->FcbList.Flink;
while (!bFound && Link != &Vcb->FcbList)
{
TmpFcb = CONTAINING_RECORD(Link, EXT2_FCB, Next);
if (TmpFcb && TmpFcb->Identifier.Type == FCB)
{
#if DBG
KdPrint(("Ext2OpenFile: [%s,%xh]\n", TmpFcb->DbgFileName, TmpFcb->inode));
#endif
if (TmpFcb->inode == inode)
{
KdPrint(("Ext2OpenFile: Found FCB for %xh.\n", inode));
Fcb = TmpFcb;
bFound = TRUE;
}
}
Link = Link->Flink;
}
if (!Fcb)
{
Fcb = Ext2AllocateFcb (
Vcb, &FileName, found_index, inode,
dir_inode, ext2_inode );
}
if (Fcb)
{
Ccb = Ext2AllocateCcb();
Fcb->OpenHandleCount++;
Vcb->OpenFileHandleCount++;
Fcb->ReferenceCount++;
Vcb->ReferenceCount++;
#if DBG
KdPrint(("Ext2OpenFile: %s refercount=%xh\n", Fcb->DbgFileName, Fcb->ReferenceCount));
#endif
io_stack->FileObject->FsContext = (void*)Fcb;
io_stack->FileObject->FsContext2 = (void*) Ccb;
io_stack->FileObject->PrivateCacheMap = NULL;
io_stack->FileObject->SectionObjectPointer = &(Fcb->SectionObject);
io_stack->FileObject->Vpb = Vcb->Vpb;
Irp->IoStatus.Information = FILE_OPENED;
Status = STATUS_SUCCESS;
#if DBG
KdPrint(("Ext2OpenFile: %s OpenCount: %u ReferCount: %u\n",
Fcb->DbgFileName, Fcb->OpenHandleCount, Fcb->ReferenceCount));
#endif
}
else
{
Irp->IoStatus.Information = 0;
Status = STATUS_OBJECT_NAME_NOT_FOUND;
KdPrint(("Ext2OpenFile: Create denied (CCB allocate error.)\n"));
}
}
__finally
{
if (VcbResourceAcquired)
{
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread() );
}
if (bFound)
{
if (ext2_inode)
ExFreePool(ext2_inode);
}
else
{
if (!Fcb && ext2_inode)
ExFreePool(ext2_inode);
}
/*
if (FileName.Buffer)
ExFreePool(FileName.Buffer);
*/
}
return Status;
}
NTSTATUS
Ext2Create (IN PEXT2_IRP_CONTEXT IrpContext)
{
PDEVICE_OBJECT DeviceObject;
PIRP Irp;
PIO_STACK_LOCATION io_stack;
PEXT2_VCB Vcb = 0;
NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND;
DeviceObjec
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -