📄 memory.c
字号:
/*
* COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: memory.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, Ext2AllocateIrpContext)
#pragma alloc_text(PAGE, Ext2FreeIrpContext)
#pragma alloc_text(PAGE, Ext2AllocateFcb)
#pragma alloc_text(PAGE, Ext2FreeFcb)
#pragma alloc_text(PAGE, Ext2AllocateMcb)
#pragma alloc_text(PAGE, Ext2SearchMcbTree)
#pragma alloc_text(PAGE, Ext2SearchMcb)
#pragma alloc_text(PAGE, Ext2GetFullFileName)
#pragma alloc_text(PAGE, Ext2AddMcbNode)
#pragma alloc_text(PAGE, Ext2DeleteMcbNode)
#pragma alloc_text(PAGE, Ext2GetMcbDepth)
#pragma alloc_text(PAGE, Ext2CompareMcb)
#pragma alloc_text(PAGE, Ext2FindUnusedMcb)
#pragma alloc_text(PAGE, Ext2FreeMcbTree)
#pragma alloc_text(PAGE, Ext2CheckBitmapConsistency)
#pragma alloc_text(PAGE, Ext2CheckSetBlock)
#pragma alloc_text(PAGE, Ext2InitializeVcb)
#pragma alloc_text(PAGE, Ext2FreeCcb)
#pragma alloc_text(PAGE, Ext2AllocateCcb)
#pragma alloc_text(PAGE, Ext2FreeVcb)
#pragma alloc_text(PAGE, Ext2CreateFcbFromMcb)
#endif
PEXT2_IRP_CONTEXT
Ext2AllocateIrpContext (IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp )
{
PIO_STACK_LOCATION IoStackLocation;
PEXT2_IRP_CONTEXT IrpContext;
ASSERT(DeviceObject != NULL);
ASSERT(Irp != NULL);
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
IrpContext = (PEXT2_IRP_CONTEXT) (ExAllocateFromNPagedLookasideList( &(gExt2Global->Ext2IrpContextLookasideList)));
if (IrpContext == NULL) {
IrpContext = ExAllocatePool( NonPagedPool, sizeof(EXT2_IRP_CONTEXT) );
//
// Zero out the irp context and indicate that it is from pool and
// not region allocated
//
RtlZeroMemory(IrpContext, sizeof(EXT2_IRP_CONTEXT));
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_FROM_POOL);
} else {
//
// Zero out the irp context and indicate that it is from zone and
// not pool allocated
//
RtlZeroMemory(IrpContext, sizeof(EXT2_IRP_CONTEXT) );
}
if (!IrpContext)
{
return NULL;
}
IrpContext->Identifier.Type = EXT2ICX;
IrpContext->Identifier.Size = sizeof(EXT2_IRP_CONTEXT);
IrpContext->Irp = Irp;
IrpContext->MajorFunction = IoStackLocation->MajorFunction;
IrpContext->MinorFunction = IoStackLocation->MinorFunction;
IrpContext->DeviceObject = DeviceObject;
IrpContext->FileObject = IoStackLocation->FileObject;
if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL ||
IrpContext->MajorFunction == IRP_MJ_DEVICE_CONTROL ||
IrpContext->MajorFunction == IRP_MJ_SHUTDOWN)
{
IrpContext->IsSynchronous = TRUE;
}
else if (IrpContext->MajorFunction == IRP_MJ_CLEANUP ||
IrpContext->MajorFunction == IRP_MJ_CLOSE)
{
IrpContext->IsSynchronous = FALSE;
}
else
{
IrpContext->IsSynchronous = IoIsOperationSynchronous(Irp);
}
//
// Temporary workaround for a bug in close that makes it reference a
// fileobject when it is no longer valid.
//
if (IrpContext->MajorFunction == IRP_MJ_CLOSE)
{
IrpContext->IsSynchronous = TRUE;
}
IrpContext->IsTopLevel = (IoGetTopLevelIrp() == Irp);
IrpContext->ExceptionInProgress = FALSE;
return IrpContext;
}
VOID
Ext2FreeIrpContext (IN PEXT2_IRP_CONTEXT IrpContext)
{
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
Ext2UnpinRepinnedBcbs(IrpContext);
// Return the Irp context record to the region or to pool depending on
// its flag
if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FROM_POOL)) {
ExFreePool( IrpContext );
} else {
ExFreeToNPagedLookasideList(&(gExt2Global->Ext2IrpContextLookasideList), IrpContext);
}
}
VOID
Ext2RepinBcb (
IN PEXT2_IRP_CONTEXT IrpContext,
IN PBCB Bcb
)
{
PEXT2_REPINNED_BCBS Repinned;
ULONG i;
Repinned = &IrpContext->Repinned;
while (TRUE)
{
for (i = 0; i < EXT2_REPINNED_BCBS_ARRAY_SIZE; i += 1)
{
if (Repinned->Bcb[i] == Bcb)
{
return;
}
if (Repinned->Bcb[i] == NULL)
{
Repinned->Bcb[i] = Bcb;
CcRepinBcb( Bcb );
return;
}
}
if (Repinned->Next == NULL)
{
Repinned->Next = FsRtlAllocatePool( PagedPool, sizeof(EXT2_REPINNED_BCBS) );
RtlZeroMemory( Repinned->Next, sizeof(EXT2_REPINNED_BCBS) );
}
Repinned = Repinned->Next;
}
}
VOID
Ext2UnpinRepinnedBcbs (
IN PEXT2_IRP_CONTEXT IrpContext
)
{
IO_STATUS_BLOCK RaiseIosb;
PEXT2_REPINNED_BCBS Repinned;
BOOLEAN WriteThroughToDisk;
PFILE_OBJECT FileObject = NULL;
BOOLEAN ForceVerify = FALSE;
ULONG i;
Repinned = &IrpContext->Repinned;
RaiseIosb.Status = STATUS_SUCCESS;
WriteThroughToDisk = (BOOLEAN) (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH) ||
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FLOPPY));
while (Repinned != NULL)
{
for (i = 0; i < EXT2_REPINNED_BCBS_ARRAY_SIZE; i += 1)
{
if (Repinned->Bcb[i] != NULL)
{
IO_STATUS_BLOCK Iosb;
if ( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FLOPPY) )
{
FileObject = CcGetFileObjectFromBcb( Repinned->Bcb[i] );
}
CcUnpinRepinnedBcb( Repinned->Bcb[i],
WriteThroughToDisk,
&Iosb );
if ( !NT_SUCCESS(Iosb.Status) )
{
if (RaiseIosb.Status == STATUS_SUCCESS)
{
RaiseIosb = Iosb;
}
if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FLOPPY) &&
(IrpContext->MajorFunction != IRP_MJ_CLEANUP) &&
(IrpContext->MajorFunction != IRP_MJ_FLUSH_BUFFERS) &&
(IrpContext->MajorFunction != IRP_MJ_SET_INFORMATION))
{
CcPurgeCacheSection( FileObject->SectionObjectPointer,
NULL,
0,
FALSE );
ForceVerify = TRUE;
}
}
Repinned->Bcb[i] = NULL;
}
else
{
break;
}
}
if (Repinned != &IrpContext->Repinned)
{
PEXT2_REPINNED_BCBS Saved;
Saved = Repinned->Next;
ExFreePool( Repinned );
Repinned = Saved;
}
else
{
Repinned = Repinned->Next;
IrpContext->Repinned.Next = NULL;
}
}
if (!NT_SUCCESS(RaiseIosb.Status))
{
if (ForceVerify && FileObject)
{
SetFlag(FileObject->DeviceObject->Flags, DO_VERIFY_VOLUME);
IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
FileObject->DeviceObject );
}
IrpContext->Irp->IoStatus = RaiseIosb;
Ext2NormalizeAndRaiseStatus(IrpContext, RaiseIosb.Status );
}
return;
}
PEXT2_FCB
Ext2AllocateFcb (IN PEXT2_VCB Vcb,
IN PEXT2_MCB Ext2Mcb,
IN PEXT2_INODE ext2_inode )
{
PEXT2_FCB Fcb;
Fcb = (PEXT2_FCB) (ExAllocateFromNPagedLookasideList( &(gExt2Global->Ext2FcbLookasideList)));
if (Fcb == NULL)
{
Fcb = (PEXT2_FCB)ExAllocatePool(NonPagedPool, sizeof(EXT2_FCB));
RtlZeroMemory(Fcb, sizeof(EXT2_FCB));
SetFlag(Fcb->Flags, FCB_FROM_POOL);
}
else
{
RtlZeroMemory(Fcb, sizeof(EXT2_FCB));
}
if (!Fcb)
{
return NULL;
}
Fcb->Identifier.Type = EXT2FCB;
Fcb->Identifier.Size = sizeof(EXT2_FCB);
FsRtlInitializeFileLock (
&Fcb->FileLockAnchor,
NULL,
NULL );
Fcb->OpenHandleCount = 0;
Fcb->ReferenceCount = 0;
Fcb->Vcb = Vcb;
#if DBG
Fcb->AnsiFileName.Length = Ext2Mcb->ShortName.Length / sizeof(WCHAR);
Fcb->AnsiFileName.MaximumLength = Ext2Mcb->ShortName.Length / sizeof(WCHAR) + 1;
Fcb->AnsiFileName.Buffer = (PUCHAR) ExAllocatePool(
PagedPool,
Ext2Mcb->ShortName.Length / sizeof(WCHAR) + 1 );
if (!Fcb->AnsiFileName.Buffer)
{
goto errorout;
}
Ext2WcharToChar(
Fcb->AnsiFileName.Buffer,
Ext2Mcb->ShortName.Buffer,
Ext2Mcb->ShortName.Length / sizeof(WCHAR)
);
Fcb->AnsiFileName.Buffer[Ext2Mcb->ShortName.Length / sizeof(WCHAR)] = 0;
#endif
Ext2Mcb->FileAttr = FILE_ATTRIBUTE_NORMAL;
if (S_ISDIR(ext2_inode->i_mode))
{
SetFlag(Ext2Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY);
}
if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) || Ext2IsReadOnly(ext2_inode->i_mode))
{
SetFlag(Ext2Mcb->FileAttr, FILE_ATTRIBUTE_READONLY);
}
Fcb->ext2_inode = ext2_inode;
Fcb->Ext2Mcb = Ext2Mcb;
Ext2Mcb->Ext2Fcb = Fcb;
RtlZeroMemory(&Fcb->CommonFCBHeader, sizeof(FSRTL_COMMON_FCB_HEADER));
Fcb->CommonFCBHeader.NodeTypeCode = (USHORT) EXT2FCB;
Fcb->CommonFCBHeader.NodeByteSize = sizeof(EXT2_FCB);
Fcb->CommonFCBHeader.IsFastIoPossible = FastIoIsNotPossible;
Fcb->CommonFCBHeader.Resource = &(Fcb->MainResource);
Fcb->CommonFCBHeader.PagingIoResource = &(Fcb->PagingIoResource);
Fcb->CommonFCBHeader.AllocationSize.QuadPart = (LONGLONG)(Fcb->ext2_inode->i_blocks * SECTOR_SIZE);
Fcb->CommonFCBHeader.FileSize.QuadPart = (LONGLONG)(Fcb->ext2_inode->i_size);
Fcb->CommonFCBHeader.ValidDataLength.QuadPart = (LONGLONG)(0x7fffffffffffffff);
Fcb->SectionObject.DataSectionObject = NULL;
Fcb->SectionObject.SharedCacheMap = NULL;
Fcb->SectionObject.ImageSectionObject = NULL;
ExInitializeResourceLite(&(Fcb->MainResource));
ExInitializeResourceLite(&(Fcb->PagingIoResource));
ExInitializeResourceLite(&(Fcb->CountResource));
InsertTailList(&Vcb->FcbList, &Fcb->Next);
/*
if (dir_inode != inode)
{
ParentFcb = Ext2SearchMcb(Vcb, dir_inode);
if (ParentFcb)
{
Fcb->ParentFcb = ParentFcb;
ExAcquireResourceExclusiveLite(&ParentFcb->CountResource, TRUE);
ParentFcb->ReferenceCount++;
ExReleaseResourceForThreadLite(
&ParentFcb->CountResource,
ExGetCurrentResourceThread());
}
}
*/
#if DBG
ExAcquireResourceExclusiveLite(
&gExt2Global->Resource,
TRUE );
gExt2Global->FcbAllocated++;
ExReleaseResourceForThreadLite(
&gExt2Global->Resource,
ExGetCurrentResourceThread() );
#endif
return Fcb;
#if DBG
errorout:
#endif
if (Fcb)
{
#if DBG
if (Fcb->AnsiFileName.Buffer)
ExFreePool(Fcb->AnsiFileName.Buffer);
#endif
if (FlagOn(Fcb->Flags, FCB_FROM_POOL)) {
ExFreePool( Fcb );
} else {
ExFreeToNPagedLookasideList(&(gExt2Global->Ext2FcbLookasideList), Fcb);
}
}
return NULL;
}
VOID
Ext2FreeFcb (IN PEXT2_FCB Fcb)
{
ASSERT(Fcb != NULL);
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
FsRtlUninitializeFileLock(&Fcb->FileLockAnchor);
ExDeleteResourceLite(&Fcb->CountResource);
ExDeleteResourceLite(&Fcb->MainResource);
ExDeleteResourceLite(&Fcb->PagingIoResource);
RemoveEntryList(&Fcb->Next);
Fcb->Ext2Mcb->Ext2Fcb = NULL;
if(IsFlagOn(Fcb->Flags, FCB_FILE_DELETED))
{
if (Fcb->Ext2Mcb)
{
Ext2DeleteMcbNode(Fcb->Ext2Mcb->Parent, Fcb->Ext2Mcb);
Ext2FreeMcb(Fcb->Ext2Mcb);
}
}
#if DBG
ExFreePool(Fcb->AnsiFileName.Buffer);
#endif
ExFreePool(Fcb->ext2_inode);
/*
if ( Fcb->ParentFcb )
{
ASSERT((Fcb->ParentFcb->Identifier.Type == FCB) &&
(Fcb->ParentFcb->Identifier.Size == sizeof(EXT2_FCB)));
ExAcquireResourceExclusiveLite(&Fcb->ParentFcb->CountResource, TRUE);
Fcb->ParentFcb->ReferenceCount -- ;
ExReleaseResourceForThreadLite(
&Fcb->ParentFcb->CountResource,
ExGetCurrentResourceThread());
if (!Fcb->ParentFcb->ReferenceCount)
Ext2FreeFcb(Fcb->ParentFcb);
}
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -