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

📄 fsctl.c

📁 I want to provide an example file system driver for Windows NT/2000/XP. For some time I have worked
💻 C
📖 第 1 页 / 共 2 页
字号:
            0,
            FALSE,
            &VolumeDeviceObject
            );

        if (!NT_SUCCESS(Status))
        {
            __leave;
        }

        VolumeDeviceObject->StackSize = TargetDeviceObject->StackSize;

        (IrpSp->Parameters.MountVolume.Vpb)->DeviceObject = VolumeDeviceObject;

        Vcb = (PFSD_VCB) VolumeDeviceObject->DeviceExtension;

        RtlZeroMemory(Vcb, sizeof(FSD_VCB));

        Vcb->Identifier.Type = VCB;
        Vcb->Identifier.Size = sizeof(FSD_VCB);

        ExInitializeResourceLite(&Vcb->MainResource);
        ExInitializeResourceLite(&Vcb->PagingIoResource);

        VcbResourceInitialized = TRUE;

        Vcb->Vpb = IrpSp->Parameters.MountVolume.Vpb;

        InitializeListHead(&Vcb->FcbList);

        InitializeListHead(&Vcb->NotifyList);

        FsRtlNotifyInitializeSync(&Vcb->NotifySync);

        NotifySyncInitialized = TRUE;

        Vcb->DeviceObject = VolumeDeviceObject;

        Vcb->TargetDeviceObject = TargetDeviceObject;

        Vcb->OpenFileHandleCount = 0;

        Vcb->ReferenceCount = 0;

        Vcb->Flags = 0;

        Vcb->romfs_super_block = romfs_super_block =
            (struct romfs_super_block *)
            FsdAllocatePool(NonPagedPool, SECTOR_SIZE, 'puSR');

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

        Offset.QuadPart = 0;

        Status = FsdReadBlockDevice(
            TargetDeviceObject,
            &Offset,
            SECTOR_SIZE,
            romfs_super_block
            );

        if (!NT_SUCCESS(Status))
        {
            __leave;
        }

        VolumeLabelLength = (USHORT) strnlen(
            Vcb->romfs_super_block->name,
            ROMFS_MAXFN
            );

        if (VolumeLabelLength > MAXIMUM_VOLUME_LABEL_LENGTH / 2)
        {
            VolumeLabelLength = MAXIMUM_VOLUME_LABEL_LENGTH / 2;
        }

        Vcb->Vpb->VolumeLabelLength = VolumeLabelLength * 2;

        FsdCharToWchar(
            Vcb->Vpb->VolumeLabel,
            Vcb->romfs_super_block->name,
            VolumeLabelLength
            );

        Vcb->Vpb->SerialNumber = be32_to_cpu(Vcb->romfs_super_block->checksum);

        Vcb->root_inode_number = (ROMFH_SIZE +
            strnlen(Vcb->romfs_super_block->name, ROMFS_MAXFN)
            + 1 + ROMFH_PAD) & ROMFH_MASK;

        Vcb->root_inode_number = cpu_to_be32(Vcb->root_inode_number);

        Inode = FsdAllocatePool(
            NonPagedPool,
            sizeof(struct romfs_inode) + ROMFS_MAXFN,
            'niRR'
            );

        if (Inode == NULL)
        {
            Status = STATUS_INSUFFICIENT_RESOURCES;
            __leave;
        }

        Status = FsdReadInodeByIndex(
            TargetDeviceObject,
            Vcb->root_inode_number,
            Inode
            );

        if (!NT_SUCCESS(Status))
        {
            __leave;
        }

        Vcb->root_inode = Inode;

        IoctlSize = sizeof(DISK_GEOMETRY);

        Status = FsdBlockDeviceIoControl(
            TargetDeviceObject,
            IOCTL_DISK_GET_DRIVE_GEOMETRY,
            NULL,
            0,
            &Vcb->DiskGeometry,
            &IoctlSize
            );

        if (!NT_SUCCESS(Status))
        {
            __leave;
        }

        IoctlSize = sizeof(PARTITION_INFORMATION);

        Status = FsdBlockDeviceIoControl(
            TargetDeviceObject,
            IOCTL_DISK_GET_PARTITION_INFO,
            NULL,
            0,
            &Vcb->PartitionInformation,
            &IoctlSize
            );

        if (!NT_SUCCESS(Status))
        {
            Vcb->PartitionInformation.StartingOffset.QuadPart = 0;

            Vcb->PartitionInformation.PartitionLength.QuadPart =
                Vcb->DiskGeometry.Cylinders.QuadPart *
                Vcb->DiskGeometry.TracksPerCylinder *
                Vcb->DiskGeometry.SectorsPerTrack *
                Vcb->DiskGeometry.BytesPerSector;

            Status = STATUS_SUCCESS;
        }

        InsertTailList(&FsdGlobalData.VcbList, &Vcb->Next);
    }
    __finally
    {
        if (GlobalDataResourceAcquired)
        {
            ExReleaseResourceForThreadLite(
                &FsdGlobalData.Resource,
                ExGetCurrentResourceThread()
                );
        }

        if (!NT_SUCCESS(Status))
        {
            if (Inode)
            {
                FsdFreePool(Inode);
            }

            if (romfs_super_block)
            {
                FsdFreePool(romfs_super_block);
            }

            if (NotifySyncInitialized)
            {
                FsRtlNotifyUninitializeSync(&Vcb->NotifySync);
            }

            if (VcbResourceInitialized)
            {
                ExDeleteResourceLite(&Vcb->MainResource);
                ExDeleteResourceLite(&Vcb->PagingIoResource);
            }

            if (VolumeDeviceObject)
            {
                IoDeleteDevice(VolumeDeviceObject);
            }
        }

        if (!AbnormalTermination())
        {
            if (NT_SUCCESS(Status))
            {
                ClearFlag(VolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING);
            }

            IrpContext->Irp->IoStatus.Status = Status;

            FsdCompleteRequest(
                IrpContext->Irp,
                (CCHAR)
                (NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT)
                );

            FsdFreeIrpContext(IrpContext);
        }
    }

    return Status;
}

#pragma code_seg() // end FSD_PAGED_CODE

NTSTATUS
FsdVerifyVolume (
    IN PFSD_IRP_CONTEXT IrpContext
    )
{
    PDEVICE_OBJECT          DeviceObject;
    NTSTATUS                Status = STATUS_UNSUCCESSFUL;
    PFSD_VCB                Vcb;
    BOOLEAN                 VcbResourceAcquired = FALSE;
    PIRP                    Irp;

    __try
    {
        ASSERT(IrpContext != NULL);

        ASSERT((IrpContext->Identifier.Type == ICX) &&
               (IrpContext->Identifier.Size == sizeof(FSD_IRP_CONTEXT)));

        DeviceObject = IrpContext->DeviceObject;

        if (DeviceObject == FsdGlobalData.DeviceObject)
        {
            Status = STATUS_INVALID_DEVICE_REQUEST;
            __leave;
        }

        Vcb = (PFSD_VCB) DeviceObject->DeviceExtension;

        ASSERT(Vcb != NULL);

        ASSERT((Vcb->Identifier.Type == VCB) &&
               (Vcb->Identifier.Size == sizeof(FSD_VCB)));

        ExAcquireResourceExclusiveLite(
            &Vcb->MainResource,
            TRUE
            );

        VcbResourceAcquired = TRUE;

        if (!FlagOn(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME))
        {
            Status = STATUS_SUCCESS;
            __leave;
        }

        Irp = IrpContext->Irp;

        Status = FsdIsDeviceSameRomfs(
            Vcb->TargetDeviceObject,
            be32_to_cpu(Vcb->romfs_super_block->checksum)
            );

        if (NT_SUCCESS(Status))
        {
            ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME);

            KdPrint((DRIVER_NAME ": Volume verify succeeded\n"));

            __leave;
        }
        else
        {
            ExReleaseResourceForThreadLite(
                &Vcb->MainResource,
                ExGetCurrentResourceThread()
                );

            VcbResourceAcquired = FALSE;

            FsdPurgeVolume(Vcb, FALSE);

            ExAcquireResourceExclusiveLite(
                &Vcb->MainResource,
                TRUE
                );

            VcbResourceAcquired = TRUE;

            SetFlag(Vcb->Flags, VCB_DISMOUNT_PENDING);

            ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME);

            KdPrint((DRIVER_NAME ": Volume verify failed\n"));

            __leave;
        }
    }
    __finally
    {
        if (VcbResourceAcquired)
        {
            ExReleaseResourceForThreadLite(
                &Vcb->MainResource,
                ExGetCurrentResourceThread()
                );
        }

        if (!AbnormalTermination())
        {
            IrpContext->Irp->IoStatus.Status = Status;

            FsdCompleteRequest(
                IrpContext->Irp,
                (CCHAR)
                (NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT)
                );

            FsdFreeIrpContext(IrpContext);
        }
    }

    return Status;
}

#pragma code_seg(FSD_PAGED_CODE)

typedef struct _FCB_LIST_ENTRY {
    PFSD_FCB    Fcb;
    LIST_ENTRY  Next;
} FCB_LIST_ENTRY, *PFCB_LIST_ENTRY;

VOID
FsdPurgeVolume (
    IN PFSD_VCB Vcb,
    IN BOOLEAN  FlushBeforePurge
    )
{
    BOOLEAN         VcbResourceAcquired = FALSE;
    PFSD_FCB        Fcb;
    LIST_ENTRY      FcbList;
    PLIST_ENTRY     ListEntry;
    PFCB_LIST_ENTRY FcbListEntry;

    __try
    {
        ASSERT(Vcb != NULL);

        ASSERT((Vcb->Identifier.Type == VCB) &&
               (Vcb->Identifier.Size == sizeof(FSD_VCB)));

        ExAcquireResourceSharedLite(
            &Vcb->MainResource,
            TRUE
            );

        VcbResourceAcquired = TRUE;

#ifndef FSD_RO
        if (FlagOn(Vcb->Flags, VCB_READ_ONLY))
        {
            FlushBeforePurge = FALSE;
        }
#endif

        InitializeListHead(&FcbList);

        for (
            ListEntry = Vcb->FcbList.Flink;
            ListEntry != &Vcb->FcbList;
            ListEntry = ListEntry->Flink
            )
        {
            Fcb = CONTAINING_RECORD(ListEntry, FSD_FCB, Next);

            ExAcquireResourceExclusiveLite(
                &Fcb->MainResource,
                TRUE
                );

            Fcb->ReferenceCount++;

            ExReleaseResourceForThreadLite(
                &Fcb->MainResource,
                ExGetCurrentResourceThread()
                );

            FcbListEntry = FsdAllocatePool(
                NonPagedPool,
                sizeof(FCB_LIST_ENTRY),
                '1mTR'
                );

            FcbListEntry->Fcb = Fcb;

            InsertTailList(&FcbList, &FcbListEntry->Next);
        }

        ExReleaseResourceForThreadLite(
            &Vcb->MainResource,
            ExGetCurrentResourceThread()
            );

        VcbResourceAcquired = FALSE;

        while (!IsListEmpty(&FcbList))
        {
            ListEntry = RemoveHeadList(&FcbList);

            FcbListEntry = CONTAINING_RECORD(ListEntry, FCB_LIST_ENTRY, Next);

            Fcb = FcbListEntry->Fcb;

            FsdPurgeFile(Fcb, FlushBeforePurge);

            Fcb->ReferenceCount--;

            if (!Fcb->ReferenceCount)
            {
                KdPrint(("FsdFreeFcb %s\n", Fcb->AnsiFileName.Buffer));
                FsdFreeFcb(Fcb);
            }

            FsdFreePool(FcbListEntry);
        }

        KdPrint((DRIVER_NAME ": Volume flushed and purged\n"));
    }
    __finally
    {
        if (VcbResourceAcquired)
        {
            ExReleaseResourceForThreadLite(
                &Vcb->MainResource,
                ExGetCurrentResourceThread()
                );
        }
    }
}

VOID
FsdPurgeFile (
    IN PFSD_FCB Fcb,
    IN BOOLEAN  FlushBeforePurge
    )
{
#ifndef FSD_RO
    IO_STATUS_BLOCK IoStatus;
#endif

    ASSERT(Fcb != NULL);
        
    ASSERT((Fcb->Identifier.Type == FCB) &&
           (Fcb->Identifier.Size == sizeof(FSD_FCB)));

#ifndef FSD_RO
    if (FlushBeforePurge)
    {
        KdPrint(("CcFlushCache on %s\n", Fcb->AnsiFileName.Buffer));

        CcFlushCache(&Fcb->SectionObject, NULL, 0, &IoStatus);
    }
#endif
    
    if (Fcb->SectionObject.ImageSectionObject)
    {
        KdPrint(("MmFlushImageSection on %s\n", Fcb->AnsiFileName.Buffer));

        MmFlushImageSection(&Fcb->SectionObject, MmFlushForWrite);
    }
    
    if (Fcb->SectionObject.DataSectionObject)
    {
        KdPrint(("CcPurgeCacheSection on %s\n", Fcb->AnsiFileName.Buffer));

        CcPurgeCacheSection(&Fcb->SectionObject, NULL, 0, FALSE);
    }
}

#pragma code_seg() // end FSD_PAGED_CODE

VOID
FsdSetVpbFlag (
    IN PVPB     Vpb,
    IN USHORT   Flag
    )
{
    KIRQL OldIrql;

    IoAcquireVpbSpinLock(&OldIrql);

    Vpb->Flags |= Flag;

    IoReleaseVpbSpinLock(OldIrql);
}

VOID
FsdClearVpbFlag (
    IN PVPB     Vpb,
    IN USHORT   Flag
    )
{
    KIRQL OldIrql;

    IoAcquireVpbSpinLock(&OldIrql);

    Vpb->Flags &= ~Flag;

    IoReleaseVpbSpinLock(OldIrql);
}

⌨️ 快捷键说明

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