Beispiel #1
0
NTSTATUS
Ext2WriteInode (
    IN PEXT2_IRP_CONTEXT    IrpContext,
    IN PEXT2_VCB            Vcb,
    IN PEXT2_MCB            Mcb,
    IN ULONGLONG            Offset,
    IN PVOID                Buffer,
    IN ULONG                Size,
    IN BOOLEAN              bDirectIo,
    OUT PULONG              BytesWritten
    )
{
    PEXT2_EXTENT    Chain = NULL;
    NTSTATUS        Status = STATUS_UNSUCCESSFUL;

    __try {

        if (BytesWritten) {
            *BytesWritten = 0;
        }

        Status = Ext2BuildExtents (
                     IrpContext,
                     Vcb,
                     Mcb,
                     Offset,
                     Size,
                     S_ISDIR(Mcb->Inode.i_mode) ? FALSE : TRUE,
                     &Chain
                 );

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

        if (Chain == NULL) {
            Status = STATUS_SUCCESS;
            __leave;
        }

        if (bDirectIo) {

            ASSERT(IrpContext != NULL);

            //
            // We assume the offset is aligned.
            //

            Status = Ext2ReadWriteBlocks(
                         IrpContext,
                         Vcb,
                         Chain,
                         Size
                     );

        } else {

            PEXT2_EXTENT Extent;
            for (Extent = Chain; Extent != NULL; Extent = Extent->Next) {

                if ( !Ext2SaveBuffer(
                            IrpContext,
                            Vcb,
                            Extent->Lba,
                            Extent->Length,
                            (PVOID)((PUCHAR)Buffer + Extent->Offset)
                        )) {
                    __leave;
                }
            }

            if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {

                DEBUG(DL_FLP, ("Ext2WriteInode is starting FlushingDpc...\n"));
                Ext2StartFloppyFlushDpc(Vcb, NULL, NULL);
            }

            Status = STATUS_SUCCESS;
        }

    } __finally {

        if (Chain) {
            Ext2DestroyExtentChain(Chain);
        }

        if (NT_SUCCESS(Status) && BytesWritten) {
            *BytesWritten = Size;
        }
    }

    return Status;
}
Beispiel #2
0
NTSTATUS
Ext2ReadInode (
    IN PEXT2_IRP_CONTEXT    IrpContext,
    IN PEXT2_VCB            Vcb,
    IN PEXT2_MCB            Mcb,
    IN ULONGLONG            Offset,
    IN PVOID                Buffer,
    IN ULONG                Size,
    IN BOOLEAN              bDirectIo,
    OUT PULONG              BytesRead
)
{
    PEXT2_EXTENT    Chain = NULL;
    PEXT2_EXTENT    Extent = NULL, Prev = NULL;

    IO_STATUS_BLOCK IoStatus;
    NTSTATUS        Status = STATUS_UNSUCCESSFUL;
    ULONG           RealSize ;

    if (BytesRead) {
        *BytesRead = 0;
    }

    __try {

        Ext2ReferMcb(Mcb);

        ASSERT((Mcb->Identifier.Type == EXT2MCB) &&
               (Mcb->Identifier.Size == sizeof(EXT2_MCB)));

        if ((Mcb->Identifier.Type != EXT2MCB) ||
                (Mcb->Identifier.Size != sizeof(EXT2_MCB))) {
            __leave;
        }

        if (Buffer == NULL && IrpContext != NULL)
            Buffer = Ext2GetUserBuffer(IrpContext->Irp);


        /* handle fast symlinks */
        if (S_ISLNK(Mcb->Inode.i_mode) &&
                Mcb->Inode.i_size < EXT2_LINKLEN_IN_INODE) {

            PUCHAR Data = (PUCHAR) (&Mcb->Inode.i_block[0]);

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

            if (Offset < EXT2_LINKLEN_IN_INODE) {
                if ((ULONG)Offset + Size >= EXT2_LINKLEN_IN_INODE)
                    Size = EXT2_LINKLEN_IN_INODE - (ULONG)Offset - 1;
                RtlCopyMemory(Buffer, Data + (ULONG)Offset, Size);
                Status = STATUS_SUCCESS;
            } else {
                Status = STATUS_END_OF_FILE;
            }
            __leave;
        }

        //
        // Build the scatterred block ranges to be read
        //

        if (bDirectIo) {
            RealSize = CEILING_ALIGNED(ULONG, Size, SECTOR_SIZE - 1);
        } else {
            RealSize = Size;
        }

        Status = Ext2BuildExtents(
                     IrpContext,
                     Vcb,
                     Mcb,
                     Offset,
                     RealSize,
                     FALSE,
                     &Chain
                 );

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

        if (Chain == NULL) {
            SafeZeroMemory((PCHAR)Buffer, Size);
            Status = STATUS_SUCCESS;
            __leave;
        }

        /* for sparse file, we need zero the gaps */
        for (Extent = Chain; Buffer != NULL && Extent != NULL; Extent = Extent->Next) {
            if (NULL == Prev) {
                ASSERT(Extent == Chain);
                if (Extent->Offset) {
                    SafeZeroMemory((PCHAR)Buffer, Extent->Offset);
                }
            } else if (Extent->Offset > (Prev->Offset + Prev->Length)) {
                SafeZeroMemory((PCHAR)Buffer + Prev->Offset + Prev->Length,
                               Extent->Offset - Prev->Offset - Prev->Length);
            }
            if (NULL == Extent->Next) {
                if (Extent->Offset + Extent->Length < Size) {
                    SafeZeroMemory((PCHAR)Buffer + Extent->Offset + Extent->Length,
                                   Size - Extent->Offset - Extent->Length);
                }
            }
            Prev = Extent;
        }

        if (bDirectIo) {

            ASSERT(IrpContext != NULL);

            // Offset should be SECTOR_SIZE aligned ...
            Status = Ext2ReadWriteBlocks(
                         IrpContext,
                         Vcb,
                         Chain,
                         Size
                     );
        } else {

            for (Extent = Chain; Extent != NULL; Extent = Extent->Next) {

                if (!CcCopyRead(
                            Vcb->Volume,
                            (PLARGE_INTEGER)(&(Extent->Lba)),
                            Extent->Length,
                            PIN_WAIT,
                            (PVOID)((PUCHAR)Buffer + Extent->Offset),
                            &IoStatus
                        )) {
                    Status = STATUS_CANT_WAIT;
                } else {
                    Status = IoStatus.Status;
                }

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

    } __finally {

        if (Chain) {
            Ext2DestroyExtentChain(Chain);
        }

        Ext2DerefMcb(Mcb);
    }

    if (NT_SUCCESS(Status)) {
        if (BytesRead)
            *BytesRead = Size;
    }

    return Status;
}
Beispiel #3
0
NTSTATUS
Ext2WriteInode (
    IN PEXT2_IRP_CONTEXT    IrpContext,
    IN PEXT2_VCB            Vcb,
    IN PEXT2_MCB            Mcb,
    IN ULONGLONG            Offset,
    IN PVOID                Buffer,
    IN ULONG                Size,
    IN BOOLEAN              bDirectIo,
    OUT PULONG              dwRet
)
{
    PEXT2_EXTENT    Chain = NULL;
    NTSTATUS        Status = STATUS_UNSUCCESSFUL;

    BOOLEAN         bAlloc = FALSE;

    __try {

        if (dwRet) {
            *dwRet = 0;
        }

        /* For file/non pagingio, we support the allocation on writing. */

        if (!IsFlagOn(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) {
            if (!(IrpContext->Irp->Flags  & IRP_PAGING_IO)) {
                bAlloc = TRUE;
            }
        }

        Status = Ext2BuildExtents (
                     IrpContext,
                     Vcb,
                     Mcb,
                     Offset,
                     Size,
                     bAlloc,
                     &Chain
                 );

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

        if (Chain == NULL) {
            Status = STATUS_SUCCESS;
            __leave;
        }

        if (bDirectIo) {

            ASSERT(IrpContext != NULL);

            //
            // We assume the offset is aligned.
            //

            Status = Ext2ReadWriteBlocks(
                         IrpContext,
                         Vcb,
                         Chain,
                         Size,
                         FALSE
                     );

        } else {

            PEXT2_EXTENT Extent;
            for (Extent = Chain; Extent != NULL; Extent = Extent->Next) {

                if ( !Ext2SaveBuffer(
                            IrpContext,
                            Vcb,
                            Extent->Lba,
                            Extent->Length,
                            (PVOID)((PUCHAR)Buffer + Extent->Offset)
                        )) {
                    __leave;
                }
            }

            if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {

                DEBUG(DL_FLP, ("Ext2WriteInode is starting FlushingDpc...\n"));
                Ext2StartFloppyFlushDpc(Vcb, NULL, NULL);
            }

            Status = STATUS_SUCCESS;
        }

    } __finally {

        if (Chain) {
            Ext2DestroyExtentChain(Chain);
        }

        if (NT_SUCCESS(Status)) {
            if (dwRet) *dwRet = Size;
        }
    }

    return Status;
}