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

📄 fileinfo.c

📁 一个windows 文件系统驱动源码
💻 C
📖 第 1 页 / 共 3 页
字号:
				        Status = STATUS_USER_MAPPED_FILE;
                        __leave;
			        }

                    if (NT_SUCCESS(Status))
                    {
                        CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->CommonFCBHeader.AllocationSize)));
                        SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
                    }
                }
            }

            break;

        case FileDispositionInformation:
            {
                PFILE_DISPOSITION_INFORMATION FDI = (PFILE_DISPOSITION_INFORMATION)Buffer;
                
                Status = Ext2SetDispositionInfo(IrpContext, Vcb, Fcb, FDI->DeleteFile);
            }

            break;

        case FileRenameInformation:
            {
                Status = Ext2SetRenameInfo(IrpContext, Vcb, Fcb);
            }

            break;

            //
            // This is the only set file information request supported on read
            // only file systems
            //
        case FilePositionInformation:
            {
                PFILE_POSITION_INFORMATION FilePositionInformation;
                
                if (Length < sizeof(FILE_POSITION_INFORMATION))
                {
                    Status = STATUS_INVALID_PARAMETER;
                    __leave;
                }
                
                FilePositionInformation = (PFILE_POSITION_INFORMATION) Buffer;
                
                if ((FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) &&
                    (FilePositionInformation->CurrentByteOffset.LowPart &
                    DeviceObject->AlignmentRequirement) )
                {
                    Status = STATUS_INVALID_PARAMETER;
                    __leave;
                }
                
                FileObject->CurrentByteOffset =
                    FilePositionInformation->CurrentByteOffset;
                
                Status = STATUS_SUCCESS;
                __leave;
            }

            break;
            
        default:
            Status = STATUS_INVALID_INFO_CLASS;
        }
    }
    __finally
    {
        
        if (FcbPagingIoResourceAcquired)
        {
            ExReleaseResourceForThreadLite(
                &Fcb->PagingIoResource,
                ExGetCurrentResourceThread() );
        }
        
        if (FcbMainResourceAcquired)
        {
            ExReleaseResourceForThreadLite(
                &Fcb->MainResource,
                ExGetCurrentResourceThread() );
        }
        
        if (VcbResourceAcquired)
        {
            ExReleaseResourceForThreadLite(
                &Vcb->MainResource,
                ExGetCurrentResourceThread() );
        }
        
        if (!IrpContext->ExceptionInProgress)
        {
            if (Status == STATUS_PENDING)
            {
                Ext2QueueRequest(IrpContext);
            }
            else
            {
                IrpContext->Irp->IoStatus.Status = Status;
                
                Ext2CompleteRequest(
                    IrpContext->Irp,
                    (CCHAR)
                    (NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
                
                Ext2FreeIrpContext(IrpContext);
            }
        }
    }
    
    return Status;
}

BOOLEAN
Ext2ExpandFileAllocation(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb, PEXT2_FCB Fcb, PLARGE_INTEGER AllocationSize)
{
    ULONG   dwRet = 0;
    BOOLEAN bRet = TRUE;

    if (AllocationSize->QuadPart <= Fcb->CommonFCBHeader.AllocationSize.QuadPart)
        return TRUE;

    if (((LONGLONG)Vcb->ext2_super_block->s_free_blocks_count) * Vcb->ext2_block <= (AllocationSize->QuadPart - Fcb->CommonFCBHeader.AllocationSize.QuadPart))
    {
        Ext2DbgPrint(D_FILEINFO, "Ext2ExpandFileAllocation: There is no enough disk space available.\n");
        return FALSE;
    }

    while (bRet && (AllocationSize->QuadPart > Fcb->CommonFCBHeader.AllocationSize.QuadPart))
    {
        bRet = Ext2ExpandInode(IrpContext, Vcb, Fcb, &dwRet);
    }
    
    return bRet;
}

BOOLEAN
Ext2TruncateFileAllocation(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb, PEXT2_FCB Fcb, PLARGE_INTEGER AllocationSize)
{
    BOOLEAN bRet = TRUE;
    
    while (bRet && (AllocationSize->QuadPart < Fcb->CommonFCBHeader.AllocationSize.QuadPart))
    {
        bRet = Ext2TruncateInode(IrpContext, Vcb, Fcb);
    }

    return bRet;
}

NTSTATUS
Ext2SetDispositionInfo(
            PEXT2_IRP_CONTEXT IrpContext,
            PEXT2_VCB Vcb,
            PEXT2_FCB Fcb,
            BOOLEAN bDelete)
{
    PIRP    Irp = IrpContext->Irp;
    PIO_STACK_LOCATION IrpSp;

    IrpSp = IoGetCurrentIrpStackLocation(Irp);

    Ext2DbgPrint(D_FILEINFO, "Ext2SetDispositionInfo: bDelete=%x\n", bDelete);
    
    if (bDelete)
    {
        if (!MmFlushImageSection( &Fcb->SectionObject,
                                  MmFlushForDelete ))
        {
            return STATUS_CANNOT_DELETE;
        }

        if (Fcb->Ext2Mcb->Inode == EXT2_ROOT_INO)
        {
            return STATUS_CANNOT_DELETE;
        }

        if (IsFlagOn(Fcb->Ext2Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
        {
            if (!Ext2IsDirectoryEmpty(Vcb, Fcb))
            {
                return STATUS_DIRECTORY_NOT_EMPTY;
            }
        }

        SetFlag(Fcb->Flags, FCB_DELETE_PENDING);
        IrpSp->FileObject->DeletePending = TRUE;

        if (IsFlagOn(Fcb->Ext2Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
        {
            FsRtlNotifyFullChangeDirectory( Vcb->NotifySync,
                                            &Vcb->NotifyList,
                                            Fcb,
                                            NULL,
                                            FALSE,
                                            FALSE,
                                            0,
                                            NULL,
                                            NULL,
                                            NULL );
        }
    }
    else
    {
        ClearFlag(Fcb->Flags, FCB_DELETE_PENDING);
        IrpSp->FileObject->DeletePending = FALSE;
    }

    return STATUS_SUCCESS;
}  

NTSTATUS
Ext2SetRenameInfo(
            PEXT2_IRP_CONTEXT IrpContext,
            PEXT2_VCB Vcb,
            PEXT2_FCB Fcb)
{
    PEXT2_FCB               TargetDcb;
    PEXT2_MCB               Mcb;

    PEXT2_MCB               TargetMcb;
    EXT2_INODE              TargetIno;

    UNICODE_STRING          FileName;
    
    NTSTATUS                Status;

    PIRP                    Irp;
    PIO_STACK_LOCATION      IrpSp;

    PFILE_OBJECT            FileObject;
    PFILE_OBJECT            TargetObject;
    BOOLEAN                 ReplaceIfExists;

    PFILE_RENAME_INFORMATION    FRI;

    if (Fcb->Ext2Mcb->Inode == EXT2_ROOT_INO)
    {
        Status = STATUS_INVALID_PARAMETER;
        goto errorout;
    }

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

    FileObject = IrpSp->FileObject;
    TargetObject = IrpSp->Parameters.SetFile.FileObject;
    ReplaceIfExists = IrpSp->Parameters.SetFile.ReplaceIfExists;

    FRI = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;

    if (TargetObject == NULL)
    {
        UNICODE_STRING  NewName;

        NewName.Buffer = FRI->FileName;
        NewName.MaximumLength = NewName.Length = (USHORT)FRI->FileNameLength;

        while (NewName.Length > 0 && NewName.Buffer[NewName.Length/2 - 1] == L'\\')
        {
            NewName.Buffer[NewName.Length/2 - 1] = 0;
            NewName.Length -= 2;
        }

        while (NewName.Length > 0 && NewName.Buffer[NewName.Length/2 - 1] != L'\\')
        {
            NewName.Length -= 2;
        }

        NewName.Buffer = (USHORT *)((UCHAR *)NewName.Buffer + NewName.Length);
        NewName.Length = (USHORT)(FRI->FileNameLength - NewName.Length);

        FileName = NewName;

        TargetDcb = NULL;
        Mcb = Fcb->Ext2Mcb->Parent;
        
        if (FileName.Length >= EXT2_NAME_LEN*sizeof(USHORT))
        {
            Status = STATUS_OBJECT_NAME_INVALID;
            goto errorout;
        }
    }
    else
    {
        TargetDcb = (PEXT2_FCB)(TargetObject->FsContext);
        if (!TargetDcb || TargetDcb->Vcb != Vcb)
        {
            Status = STATUS_INVALID_PARAMETER;
            goto errorout;
        }

        Mcb = TargetDcb->Ext2Mcb;

        FileName = TargetObject->FileName;
    }

    if (Mcb->Inode == Fcb->Ext2Mcb->Parent->Inode)
    {
        if (FsRtlAreNamesEqual( &FileName,
                                &(Fcb->Ext2Mcb->ShortName),
                                FALSE,
                                NULL ))
        {
            Status = STATUS_SUCCESS;
            goto errorout;
        }
    }

    TargetDcb = Mcb->Ext2Fcb;

    if (!TargetDcb)
        TargetDcb = Ext2CreateFcbFromMcb(Vcb, Mcb);

    if (Mcb->Inode != Fcb->Ext2Mcb->Parent->Inode)
        Ext2CreateFcbFromMcb(Vcb, Fcb->Ext2Mcb->Parent);

    if (!TargetDcb || !(Fcb->Ext2Mcb->Parent->Ext2Fcb))
    {
        Status = STATUS_UNSUCCESSFUL;

        goto errorout;
    }

    TargetMcb = NULL;
    Status = Ext2LookupFileName(
                Vcb,
                &FileName,
                TargetDcb,
                &TargetMcb,
                &TargetIno ); 

    if (NT_SUCCESS(Status))   
    {
        if ( (!ReplaceIfExists) ||
             (IsFlagOn(TargetMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) ||
             (IsFlagOn(TargetMcb->FileAttr, FILE_ATTRIBUTE_READONLY)))
        {
            Status = STATUS_OBJECT_NAME_COLLISION;
            goto errorout;
        }

        if (ReplaceIfExists)
        {
            Status = STATUS_NOT_IMPLEMENTED;
            goto errorout;
        }
    }

    Status = Ext2RemoveEntry(IrpContext, Vcb, Fcb->Ext2Mcb->Parent->Ext2Fcb, Fcb->Ext2Mcb->Inode);
 
    if (IsFlagOn(Fcb->Ext2Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
        Status = Ext2AddEntry(IrpContext, Vcb, TargetDcb, EXT2_FT_DIR, Fcb->Ext2Mcb->Inode, &FileName);
    else
        Status = Ext2AddEntry(IrpContext, Vcb, TargetDcb, EXT2_FT_REG_FILE, Fcb->Ext2Mcb->Inode, &FileName);

    if (NT_SUCCESS(Status))
    {
        if (Fcb->Ext2Mcb->ShortName.MaximumLength < (FileName.Length + 2))
        {
            ExFreePool(Fcb->Ext2Mcb->ShortName.Buffer);
            Fcb->Ext2Mcb->ShortName.Buffer = 
                ExAllocatePool(PagedPool, FileName.Length + 2);

            if (!Fcb->Ext2Mcb->ShortName.Buffer)
            {
                Status = STATUS_INSUFFICIENT_RESOURCES;
                goto errorout;
            }

            Fcb->Ext2Mcb->ShortName.MaximumLength = FileName.Length + 2;
        }

        {
            RtlCopyMemory(Fcb->Ext2Mcb->ShortName.Buffer, FileName.Buffer, FileName.Length);
            Fcb->Ext2Mcb->ShortName.Length = FileName.Length;
        }
    
#if DBG    
        if (Fcb->AnsiFileName.Length < (FileName.Length / 2 + 1))
        {
            ExFreePool(Fcb->AnsiFileName.Buffer);
            Fcb->AnsiFileName.Buffer = 
                ExAllocatePool(PagedPool, FileName.Length / 2 + 1);

            if (!Fcb->AnsiFileName.Buffer)
            {
                Status = STATUS_INSUFFICIENT_RESOURCES;
                goto errorout;
            }

            Fcb->AnsiFileName.MaximumLength = FileName.Length / 2 + 1;
        }

        Fcb->AnsiFileName.Length = FileName.Length / 2;

        Ext2WcharToChar(
            Fcb->AnsiFileName.Buffer,
            FileName.Buffer,
            FileName.Length / 2 );

        Fcb->AnsiFileName.Buffer[FileName.Length / sizeof(WCHAR)] = 0;

#endif

        Ext2DeleteMcbNode(Fcb->Ext2Mcb->Parent, Fcb->Ext2Mcb);
        Ext2AddMcbNode(Mcb, Fcb->Ext2Mcb);
    }

errorout:

    return Status;
}

⌨️ 快捷键说明

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