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

📄 fsctl.c

📁 This is a ReiserFs file system driver for Windows NT/2000/XP/Vista.
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * COPYRIGHT:        GNU GENERAL PUBLIC LICENSE VERSION 2
 * PROJECT:          ReiserFs file system driver for Windows NT/2000/XP/Vista.
 * FILE:             fsctl.c
 * PURPOSE:          
 * PROGRAMMER:       Mark Piper, Matt Wu, Bo Brant閚.
 * HOMEPAGE:         
 * UPDATE HISTORY: 
 */

/* INCLUDES *****************************************************************/

#include "rfsd.h"

/* GLOBALS ***************************************************************/

extern PRFSD_GLOBAL RfsdGlobal;

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

BOOLEAN
RfsdIsMediaWriteProtected (
    IN PRFSD_IRP_CONTEXT  IrpContext,
    IN PDEVICE_OBJECT     TargetDevice);

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, RfsdSetVpbFlag)
#pragma alloc_text(PAGE, RfsdClearVpbFlag)
#pragma alloc_text(PAGE, RfsdIsHandleCountZero)
#pragma alloc_text(PAGE, RfsdLockVcb)
#pragma alloc_text(PAGE, RfsdLockVolume)
#pragma alloc_text(PAGE, RfsdUnlockVcb)
#pragma alloc_text(PAGE, RfsdUnlockVolume)
#pragma alloc_text(PAGE, RfsdAllowExtendedDasdIo)
#pragma alloc_text(PAGE, RfsdUserFsRequest)
#pragma alloc_text(PAGE, RfsdIsMediaWriteProtected)
#pragma alloc_text(PAGE, RfsdMountVolume)
#pragma alloc_text(PAGE, RfsdCheckDismount)
#pragma alloc_text(PAGE, RfsdPurgeVolume)
#pragma alloc_text(PAGE, RfsdPurgeFile)
#pragma alloc_text(PAGE, RfsdDismountVolume)
#pragma alloc_text(PAGE, RfsdIsVolumeMounted)
#pragma alloc_text(PAGE, RfsdVerifyVolume)
#pragma alloc_text(PAGE, RfsdFileSystemControl)
#endif


VOID
RfsdSetVpbFlag (
        IN PVPB     Vpb,
        IN USHORT   Flag )
{
    KIRQL OldIrql;
    
    IoAcquireVpbSpinLock(&OldIrql);
    
    Vpb->Flags |= Flag;
    
    IoReleaseVpbSpinLock(OldIrql);
}

VOID
RfsdClearVpbFlag (
          IN PVPB     Vpb,
          IN USHORT   Flag )
{
    KIRQL OldIrql;
    
    IoAcquireVpbSpinLock(&OldIrql);
    
    Vpb->Flags &= ~Flag;
    
    IoReleaseVpbSpinLock(OldIrql);
}

BOOLEAN
RfsdIsHandleCountZero(IN PRFSD_VCB Vcb)
{
    PRFSD_FCB   Fcb;
    PLIST_ENTRY List;

    for( List = Vcb->FcbList.Flink;
         List != &Vcb->FcbList;
         List = List->Flink )  {

        Fcb = CONTAINING_RECORD(List, RFSD_FCB, Next);

        ASSERT((Fcb->Identifier.Type == RFSDFCB) &&
               (Fcb->Identifier.Size == sizeof(RFSD_FCB)));

        RfsdPrint((DBG_INFO, "RfsdIsHandleCountZero: Key:%x,%xh File:%S OpenHandleCount=%xh\n",
			Fcb->RfsdMcb->Key.k_dir_id, Fcb->RfsdMcb->Key.k_objectid, Fcb->RfsdMcb->ShortName.Buffer, Fcb->OpenHandleCount));

        if (Fcb->OpenHandleCount) {
            return FALSE;
        }
    }

    return TRUE;
}

NTSTATUS
RfsdLockVcb (IN PRFSD_VCB    Vcb,
             IN PFILE_OBJECT FileObject)
{
    NTSTATUS           Status;
   
    __try {

        if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
            RfsdPrint((DBG_INFO, "RfsdLockVolume: Volume is already locked.\n"));
            
            Status = STATUS_ACCESS_DENIED;
            
            __leave;
        }
        
        if (Vcb->OpenFileHandleCount > (ULONG)(FileObject ? 1 : 0)) {
            RfsdPrint((DBG_INFO, "RfsdLockVcb: There are still opened files.\n"));
            
            Status = STATUS_ACCESS_DENIED;
            
            __leave;
        }
        
        if (!RfsdIsHandleCountZero(Vcb)) {
            RfsdPrint((DBG_INFO, "RfsdLockVcb: Thare are still opened files.\n"));
            
            Status = STATUS_ACCESS_DENIED;
            
            __leave;
        }
        
        SetFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
        
        RfsdSetVpbFlag(Vcb->Vpb, VPB_LOCKED);

        Vcb->LockFile = FileObject;
        
        RfsdPrint((DBG_INFO, "RfsdLockVcb: Volume locked.\n"));
        
        Status = STATUS_SUCCESS;

    } __finally {
        // Nothing
    }
    
    return Status;
}


NTSTATUS
RfsdLockVolume (IN PRFSD_IRP_CONTEXT IrpContext)
{
    PIO_STACK_LOCATION IrpSp;
    PDEVICE_OBJECT  DeviceObject;
    PRFSD_VCB       Vcb;
    NTSTATUS        Status;
    BOOLEAN VcbResourceAcquired = FALSE;
   
    __try {

        ASSERT(IrpContext != NULL);
        
        ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
            (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
        
        DeviceObject = IrpContext->DeviceObject;
        
        Status = STATUS_UNSUCCESSFUL;

        //
        // This request is not allowed on the main device object
        //
        if (DeviceObject == RfsdGlobal->DeviceObject) {
            Status = STATUS_INVALID_PARAMETER;
            __leave;
        }
        
        Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;
        
        ASSERT(Vcb != NULL);

        ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
            (Vcb->Identifier.Size == sizeof(RFSD_VCB)));

        ASSERT(IsMounted(Vcb));

        IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp);

#if (_WIN32_WINNT >= 0x0500)
        CcWaitForCurrentLazyWriterActivity();
#endif
        ExAcquireResourceExclusiveLite(
            &Vcb->MainResource,
            TRUE            );
        
        VcbResourceAcquired = TRUE;

        Status = RfsdLockVcb(Vcb, IrpSp->FileObject);        

    } __finally {

        if (VcbResourceAcquired) {
            ExReleaseResourceForThreadLite(
                &Vcb->MainResource,
                ExGetCurrentResourceThread()
                );
        }
        
        if (!IrpContext->ExceptionInProgress) {
            RfsdCompleteIrpContext(IrpContext,  Status);
        }
    }
    
    return Status;
}

NTSTATUS
RfsdUnlockVcb ( IN PRFSD_VCB    Vcb,
                IN PFILE_OBJECT FileObject )
{
    NTSTATUS        Status;

    __try {

        if (FileObject && FileObject->FsContext != Vcb) {

            Status = STATUS_NOT_LOCKED;
            __leave;
        }
       
        if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
            RfsdPrint((DBG_ERROR, ": RfsdUnlockVcb: Volume is not locked.\n"));
            Status = STATUS_NOT_LOCKED;
            __leave;
        }

        if (Vcb->LockFile == FileObject) {

            ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
        
            RfsdClearVpbFlag(Vcb->Vpb, VPB_LOCKED);
        
            RfsdPrint((DBG_INFO, "RfsdUnlockVcb: Volume unlocked.\n"));
        
            Status = STATUS_SUCCESS;
        } else {
            Status = STATUS_NOT_LOCKED;
        }

    } __finally {
        // Nothing
    }

    return Status;
}

NTSTATUS
RfsdUnlockVolume (
         IN PRFSD_IRP_CONTEXT IrpContext
         )
{
    PIO_STACK_LOCATION IrpSp;
    PDEVICE_OBJECT  DeviceObject;
    NTSTATUS        Status;
    PRFSD_VCB       Vcb;
    BOOLEAN         VcbResourceAcquired = FALSE;
    
    __try {

        ASSERT(IrpContext != NULL);
        
        ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
            (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
        
        DeviceObject = IrpContext->DeviceObject;
        
        //
        // This request is not allowed on the main device object
        //
        if (DeviceObject == RfsdGlobal->DeviceObject) {
            Status = STATUS_INVALID_PARAMETER;
            __leave;
        }
        
        Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;
        
        ASSERT(Vcb != NULL);
        
        ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
            (Vcb->Identifier.Size == sizeof(RFSD_VCB)));

        ASSERT(IsMounted(Vcb));

        IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp);

        ExAcquireResourceExclusiveLite(
            &Vcb->MainResource,
            TRUE );
        
        VcbResourceAcquired = TRUE;

        Status = RfsdUnlockVcb(Vcb, IrpSp->FileObject);

    } __finally {

        if (VcbResourceAcquired) {
            ExReleaseResourceForThreadLite(
                &Vcb->MainResource,
                ExGetCurrentResourceThread()
                );
        }
        
        if (!IrpContext->ExceptionInProgress) {
            RfsdCompleteIrpContext(IrpContext,  Status);
        }
    }
    
    return Status;
}


NTSTATUS
RfsdInvalidateVolumes ( IN PRFSD_IRP_CONTEXT IrpContext )
{
    NTSTATUS            Status;
    PIRP                Irp;
    PIO_STACK_LOCATION  IrpSp;

    HANDLE              Handle;

    PLIST_ENTRY         ListEntry;

    PFILE_OBJECT        FileObject;
    PDEVICE_OBJECT      DeviceObject;
    BOOLEAN             GlobalResourceAcquired = FALSE;

    LUID Privilege = {SE_TCB_PRIVILEGE, 0};

    __try {

        Irp   = IrpContext->Irp;
        IrpSp = IoGetCurrentIrpStackLocation(Irp);

        if (!SeSinglePrivilegeCheck(Privilege, Irp->RequestorMode)) {
            Status = STATUS_PRIVILEGE_NOT_HELD;
            __leave;
        }

        if (
#ifndef _GNU_NTIFS_
        IrpSp->Parameters.FileSystemControl.InputBufferLength
#else
        ((PEXTENDED_IO_STACK_LOCATION)(IrpSp))->
        Parameters.FileSystemControl.InputBufferLength
#endif
            != sizeof(HANDLE)) {

            Status = STATUS_INVALID_PARAMETER;

            __leave;
        }

        Handle = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer;

        Status = ObReferenceObjectByHandle( Handle,
                                            0,
                                            *IoFileObjectType,
                                            KernelMode,
                                            &FileObject,
                                            NULL );

        if (!NT_SUCCESS(Status)) {
            __leave;
        } else {
            ObDereferenceObject(FileObject);
            DeviceObject = FileObject->DeviceObject;
        }

        RfsdPrint((DBG_INFO, "RfsdInvalidateVolumes: FileObject=%xh ...\n", FileObject));

        ExAcquireResourceExclusiveLite(
            &RfsdGlobal->Resource,
            TRUE );

        GlobalResourceAcquired = TRUE;

        ListEntry = RfsdGlobal->VcbList.Flink;

        while (ListEntry != &RfsdGlobal->VcbList)  {

            PRFSD_VCB Vcb;

            Vcb = CONTAINING_RECORD(ListEntry, RFSD_VCB, Next);

            ListEntry = ListEntry->Flink;

            RfsdPrint((DBG_INFO, "RfsdInvalidateVolumes: Vcb=%xh Vcb->Vpb=%xh...\n", Vcb, Vcb->Vpb));
            if (Vcb->Vpb && (Vcb->Vpb->RealDevice == DeviceObject))
            {
                ExAcquireResourceExclusive(&Vcb->MainResource, TRUE);
                RfsdPrint((DBG_INFO, "RfsdInvalidateVolumes: RfsdPurgeVolume...\n"));
                RfsdPurgeVolume(Vcb, FALSE);
                ClearFlag(Vcb->Flags, VCB_MOUNTED);
                ExReleaseResource(&Vcb->MainResource);
        
                //
                // Vcb is still attached on the list ......
                //

⌨️ 快捷键说明

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