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

📄 block.c

📁 一个windows 文件系统驱动源码
💻 C
字号:
/*
 * COPYRIGHT:        See COPYRIGHT.TXT
 * PROJECT:          Ext2 File System Driver for WinNT/2K/XP
 * FILE:             block.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 g_gExt2Global;

/* DEFINITIONS *************************************************************/


#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, Ext2LockUserBuffer)
#pragma alloc_text(PAGE, Ext2GetUserBuffer)
#pragma alloc_text(PAGE, Ext2ReadSync)
#pragma alloc_text(PAGE, Ext2ReadDisk)
#pragma alloc_text(PAGE, Ext2ReadDiskOverrideVerify)
#pragma alloc_text(PAGE, Ext2DiskIoControl)
#pragma alloc_text(PAGE, Ext2ReadWriteBlocks)
#pragma alloc_text(PAGE, Ext2DiskShutDown)
#endif


/* FUNCTIONS ***************************************************************/


NTSTATUS
Ext2LockUserBuffer (IN PIRP     Irp,
            IN ULONG            Length,
            IN LOCK_OPERATION   Operation)
{
    NTSTATUS Status;
    
    ASSERT(Irp != NULL);
    
    if (Irp->MdlAddress != NULL)
    {
        return STATUS_SUCCESS;
    }
    
    IoAllocateMdl(Irp->UserBuffer, Length, FALSE, FALSE, Irp);
    
    if (Irp->MdlAddress == NULL)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    
    __try
    {
        MmProbeAndLockPages(Irp->MdlAddress, Irp->RequestorMode, Operation);
        
        Status = STATUS_SUCCESS;
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        IoFreeMdl(Irp->MdlAddress);
        
        Irp->MdlAddress = NULL;
        
        Status = STATUS_INVALID_USER_BUFFER;
    }
    
    return Status;
}

PVOID
Ext2GetUserBuffer (IN PIRP Irp )
{
    ASSERT(Irp != NULL);
    
    if (Irp->MdlAddress)
    {
#if (_WIN32_WINNT >= 0x0500)
        return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
#else
        return MmGetSystemAddressForMdl(Irp->MdlAddress);
#endif
    }
    else
    {
        return Irp->UserBuffer;
    }
}

typedef struct _EXT2_CONTEXT {
        PIRP        MasterIrp;
        KEVENT      Event;
        BOOLEAN     Wait;
        ULONG       Blocks;
        ULONG       Length;
} EXT2_CONTEXT, *PEXT2_CONTEXT;


NTSTATUS
Ext2ReadWriteBlockSyncCompletionRoutine (
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PVOID Context    )
{
    PEXT2_CONTEXT pContext = (PEXT2_CONTEXT)Context;

    if (!NT_SUCCESS( Irp->IoStatus.Status )) {

        pContext->MasterIrp->IoStatus = Irp->IoStatus;
    }

    IoFreeMdl( Irp->MdlAddress );
    IoFreeIrp( Irp );

    if (InterlockedDecrement(&pContext->Blocks) == 0)
    {
        pContext->MasterIrp->IoStatus.Information = 0;

        if (NT_SUCCESS(pContext->MasterIrp->IoStatus.Status))
        {
            pContext->MasterIrp->IoStatus.Information =
                pContext->Length;
        }

        KeSetEvent( &pContext->Event, 0, FALSE );
    }

    UNREFERENCED_PARAMETER( DeviceObject );

    return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS
Ext2ReadWriteBlockAsyncCompletionRoutine (
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PVOID Context
    )
{
    PEXT2_CONTEXT pContext = (PEXT2_CONTEXT)Context;

    if (!NT_SUCCESS( Irp->IoStatus.Status ))
    {
        pContext->MasterIrp->IoStatus = Irp->IoStatus;
    }

    if (InterlockedDecrement(&pContext->Blocks) == 0)
    {

        pContext->MasterIrp->IoStatus.Information = 0;

        if (NT_SUCCESS(pContext->MasterIrp->IoStatus.Status))
        {
            pContext->MasterIrp->IoStatus.Information =
                pContext->Length;
        }

        IoMarkIrpPending( pContext->MasterIrp );

        ExFreePool(pContext);
    }

    UNREFERENCED_PARAMETER( DeviceObject );

    return STATUS_SUCCESS;

}

NTSTATUS
Ext2ReadWriteBlocks(
    IN PEXT2_IRP_CONTEXT IrpContext,
    IN PEXT2_VCB        Vcb,
    IN PEXT2_BDL        Ext2BDL,
    IN ULONG            Length,
    IN ULONG            Count,
    IN BOOLEAN          bVerify )
{
    PMDL                Mdl;
    PIRP                Irp;
    PIRP                MasterIrp = IrpContext->Irp;
    PIO_STACK_LOCATION  IrpSp;
    NTSTATUS            Status = STATUS_SUCCESS;
    PEXT2_CONTEXT       pContext = NULL;
    ULONG               i;

    ASSERT(MasterIrp);

    __try
    {

        pContext = ExAllocatePool(NonPagedPool, sizeof(EXT2_CONTEXT));

        if (!pContext)
        {
            Status = STATUS_INSUFFICIENT_RESOURCES;
            __leave;
        }

        RtlZeroMemory(pContext, sizeof(EXT2_CONTEXT));

        pContext->Wait = IrpContext->IsSynchronous;
        pContext->MasterIrp = MasterIrp;
        pContext->Blocks = Count;
        pContext->Length = 0;

        if (pContext->Wait)
                KeInitializeEvent(&(pContext->Event), NotificationEvent, FALSE);

        for (i = 0; i < Count; i++)
        {

            Irp = IoMakeAssociatedIrp( MasterIrp,
                                     (CCHAR)(Vcb->TargetDeviceObject->StackSize + 1) );
            if (!Irp)
            {
                Status = STATUS_INSUFFICIENT_RESOURCES;
                __leave;
            }

            Mdl = IoAllocateMdl( (PCHAR)MasterIrp->UserBuffer +
                    Ext2BDL[i].Offset,
                    Ext2BDL[i].Length,
                    FALSE,
                    FALSE,
                    Irp );

            if (!Mdl)
            {
                Status = STATUS_INSUFFICIENT_RESOURCES;
                __leave;
            }
            
            IoBuildPartialMdl( MasterIrp->MdlAddress,
                        Mdl,
                        (PCHAR)MasterIrp->UserBuffer + Ext2BDL[i].Offset,
                        Ext2BDL[i].Length );
                
            IoSetNextIrpStackLocation( Irp );
            IrpSp = IoGetCurrentIrpStackLocation( Irp );
                
            
            IrpSp->MajorFunction = IrpContext->MajorFunction;
            IrpSp->Parameters.Read.Length = Ext2BDL[i].Length;
            IrpSp->Parameters.Read.ByteOffset.QuadPart = Ext2BDL[i].Lba;

            IoSetCompletionRoutine(     Irp,
                                        IrpContext->IsSynchronous ?
                                        &Ext2ReadWriteBlockSyncCompletionRoutine :
                                        &Ext2ReadWriteBlockAsyncCompletionRoutine,
                                        (PVOID) pContext,
                                        TRUE,
                                        TRUE,
                                        TRUE );

            IrpSp = IoGetNextIrpStackLocation( Irp );

            IrpSp->MajorFunction = IrpContext->MajorFunction;
            IrpSp->Parameters.Read.Length = Ext2BDL[i].Length;
            IrpSp->Parameters.Read.ByteOffset.QuadPart = Ext2BDL[i].Lba;

            if ( bVerify )
            {
                SetFlag( IrpSp->Flags, SL_OVERRIDE_VERIFY_VOLUME );
            }

            Ext2BDL[i].Irp = Irp;
        }

        MasterIrp->AssociatedIrp.IrpCount = Count;

        if (IrpContext->IsSynchronous) {

            MasterIrp->AssociatedIrp.IrpCount += 1;
        }

        pContext->Length = Length;

        for (i = 0; i < Count; i++)
        {
            Status = IoCallDriver ( Vcb->TargetDeviceObject,
                                    Ext2BDL[i].Irp);
        }

        if (IrpContext->IsSynchronous)
        {
            KeWaitForSingleObject( &(pContext->Event),
                                   Executive, KernelMode, FALSE, NULL );

            KeClearEvent( &(pContext->Event) );
        }
    }

    __finally
    {
        if (IrpContext->IsSynchronous)
        {
            if (MasterIrp)
                Status = MasterIrp->IoStatus.Status;

            if (pContext)
                ExFreePool(pContext);

        }
        else
        {
            IrpContext->Irp = NULL;
            Status = STATUS_PENDING;
        }

        if ( AbnormalTermination() )
        {
            for (i = 0; i < Count; i++)
            {
                if (Ext2BDL[i].Irp != NULL )
                {
                    if ( Ext2BDL[i].Irp->MdlAddress != NULL )
                    {
                        IoFreeMdl( Ext2BDL[i].Irp->MdlAddress );
                    }
                    IoFreeIrp( Ext2BDL[i].Irp );
                }
            }
        }
    }

    return Status;
}


NTSTATUS
Ext2ReadSync(
    IN PDEVICE_OBJECT   DeviceObject,
    IN LONGLONG         Offset,
    IN ULONG            Length,
    OUT PVOID           Buffer,
    BOOLEAN             bVerify
    )
{
    KEVENT          Event;
    PIRP            Irp;
    IO_STATUS_BLOCK IoStatus;
    NTSTATUS        Status;


    ASSERT(DeviceObject != NULL);
    ASSERT(Buffer != NULL);
    
    KeInitializeEvent(&Event, NotificationEvent, FALSE);

    Irp = IoBuildSynchronousFsdRequest(
        IRP_MJ_READ,
        DeviceObject,
        Buffer,
        Length,
        (PLARGE_INTEGER)(&Offset),
        &Event,
        &IoStatus
        );

    if (!Irp)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    if (bVerify)
        SetFlag( IoGetNextIrpStackLocation( Irp )->Flags, SL_OVERRIDE_VERIFY_VOLUME );

    Status = IoCallDriver(DeviceObject, Irp);

    if (Status == STATUS_PENDING)
    {
        KeWaitForSingleObject(
            &Event,
            Suspended,
            KernelMode,
            FALSE,
            NULL
            );
        Status = IoStatus.Status;
    }

    return Status;
}


NTSTATUS
Ext2ReadDisk(IN PDEVICE_OBJECT pDeviceObject,
         IN ULONG       lba,
         IN ULONG       offset,
         IN ULONG       Size,
         IN PVOID       Buffer)
{
    ULONG       Sectors;
    NTSTATUS    Status;
    PUCHAR      Buf;
    ULONG       off = 0;

    if (offset >= SECTOR_SIZE)
        lba += offset / SECTOR_SIZE;

    off = offset % SECTOR_SIZE;
    Sectors = (off + Size + SECTOR_SIZE - 1) / SECTOR_SIZE;


    Buf = ExAllocatePool(PagedPool, Sectors * SECTOR_SIZE);
    if (!Buf)
    {
        Ext2DbgPrint(D_BLOCK, "Ext2ReadDisk: no enough memory.\n");
        return STATUS_UNSUCCESSFUL;
    }

    Status = Ext2ReadSync(pDeviceObject, (LONGLONG)lba * SECTOR_SIZE, Sectors*SECTOR_SIZE, Buf, FALSE);

    if (!NT_SUCCESS(Status))
    {
        Ext2DbgPrint(D_BLOCK, "Ext2ReadDisk: Read Block Device error.\n");
                ExFreePool(Buf);
        return Status;
    }

    RtlCopyMemory(Buffer, &Buf[off], Size);

    ExFreePool(Buf);

    return Status;
}


NTSTATUS
Ext2ReadDiskOverrideVerify (IN PDEVICE_OBJECT pDeviceObject,
                IN ULONG    DiskSector, 
                IN ULONG    SectorCount,
                IN OUT PUCHAR Buffer)
{
    LARGE_INTEGER   offset;
    NTSTATUS        Status;
    ULONG           Length;

    offset.u.LowPart = DiskSector << 9;
    offset.u.HighPart = DiskSector >> 23;
    
    Length = SECTOR_SIZE * SectorCount;
    
    Status = Ext2ReadSync(pDeviceObject, offset.QuadPart, Length, Buffer, TRUE);
    
    if (!NT_SUCCESS (Status))
    {
        Ext2DbgPrint(D_BLOCK, "Ext2ReadDiskOverrideVerify: IO failed! Error code: %x\n", Status);
        return (Status);
    }

    return Status;
}


NTSTATUS 
Ext2DiskIoControl (IN PDEVICE_OBJECT   pDeviceObject,
           IN ULONG            IoctlCode,
           IN PVOID            InputBuffer,
           IN ULONG            InputBufferSize,
           IN OUT PVOID        OutputBuffer,
           IN OUT PULONG       OutputBufferSize)
{
    ULONG           OutBufferSize = 0;
    KEVENT          Event;
    PIRP            Irp;
    IO_STATUS_BLOCK IoStatus;
    NTSTATUS        Status;
    
    ASSERT(pDeviceObject != NULL);
    
    if (OutputBufferSize)
    {
        OutBufferSize = *OutputBufferSize;
    }
    
    KeInitializeEvent(&Event, NotificationEvent, FALSE);
    
    Irp = IoBuildDeviceIoControlRequest(
        IoctlCode,
        pDeviceObject,
        InputBuffer,
        InputBufferSize,
        OutputBuffer,
        OutBufferSize,
        FALSE,
        &Event,
        &IoStatus
        );
    
    if (Irp == NULL)
    {
        Ext2DbgPrint(D_BLOCK, "Ext2DiskIoControl: Building IRQ error!\n");
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    
    Status = IoCallDriver(pDeviceObject, Irp);
    
    if (Status == STATUS_PENDING)
    {
        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
        Status = IoStatus.Status;
    }
    
    if (OutputBufferSize)
    {
        *OutputBufferSize = IoStatus.Information;
    }
    
    return Status;
}


NTSTATUS
Ext2DiskShutDown(PEXT2_VCB Vcb)
{
    PIRP                Irp;
    KEVENT              Event;

    NTSTATUS            Status;
    IO_STATUS_BLOCK     IoStatus;

    KeInitializeEvent(&Event, NotificationEvent, FALSE);

    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN,
                                       Vcb->TargetDeviceObject,
                                       NULL,
                                       0,
                                       NULL,
                                       &Event,
                                       &IoStatus);

    if (Irp)
    {
        Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);

        if (Status == STATUS_PENDING)
        {
            KeWaitForSingleObject(&Event,
                                  Executive,
                                  KernelMode,
                                  FALSE,
                                  NULL);

            Status = IoStatus.Status;
        }
    }
    else
    {
        Status = IoStatus.Status;
    }

    return Status;
}

⌨️ 快捷键说明

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