Example #1
0
File: mcb.c Project: GYGit/reactos
/*
 * @implemented
 */
BOOLEAN
NTAPI
FsRtlLookupMcbEntry(IN PMCB Mcb,
                    IN VBN Vbn,
                    OUT PLBN Lbn,
                    OUT PULONG SectorCount OPTIONAL,
                    OUT PULONG Index)
{
    BOOLEAN Return = FALSE;
    LONGLONG llLbn;
    LONGLONG llSectorCount;

    /* Call the Large version */
    Return = FsRtlLookupLargeMcbEntry(&Mcb->
                                      DummyFieldThatSizesThisStructureCorrectly,
                                      (LONGLONG)Vbn,
                                      &llLbn,
                                      &llSectorCount,
                                      NULL,
                                      NULL,
                                      Index);

    /* Return the lower 32-bits */
    *Lbn = (ULONG)llLbn;
    if (SectorCount) *SectorCount = (ULONG)llSectorCount;

    /* And return the original value */
    return Return;
}
Example #2
0
BOOLEAN
UdfLookupAllocation (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB Fcb,
    IN LONGLONG FileOffset,
    OUT PLONGLONG DiskOffset,
    OUT PULONG ByteCount
    )

/*++

Routine Description:

    This routine looks through the mapping information for the file
    to find the logical diskoffset and number of bytes at that offset.

    This routine assumes we are looking up a valid range in the file.  If
    a mapping does not exist,

Arguments:

    Fcb - Fcb representing this stream.

    FileOffset - Lookup the allocation beginning at this point.

    DiskOffset - Address to store the logical disk offset.

    ByteCount - Address to store the number of contiguous bytes beginning
        at DiskOffset above.

Return Value:

    BOOLEAN - whether the extent is unrecorded data

--*/

{
    PVCB Vcb;

    BOOLEAN Recorded = TRUE;

    BOOLEAN Result;

    LARGE_INTEGER LocalPsn;
    LARGE_INTEGER LocalSectorCount;

    PAGED_CODE();

    //
    //  Check inputs
    //

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_FCB( Fcb );

    //
    //  We will never be looking up the allocations of embedded objects.
    //

    ASSERT( !FlagOn( Fcb->FcbState, FCB_STATE_EMBEDDED_DATA ));

    Vcb = Fcb->Vcb;

    LocalPsn.QuadPart = LocalSectorCount.QuadPart = 0;

    //
    //  Lookup the entry containing this file offset.
    //

    if (FlagOn( Fcb->FcbState, FCB_STATE_VMCB_MAPPING )) {

        //
        //  Map this offset into the metadata stream.
        //

        ASSERT( SectorOffset( Vcb, FileOffset ) == 0 );

        Result = UdfVmcbVbnToLbn( &Vcb->Vmcb,
                                  SectorsFromBytes( Vcb, FileOffset ),
                                  &LocalPsn.LowPart,
                                  &LocalSectorCount.LowPart );

        ASSERT( Result );

    } else {

        //
        //  Map this offset in a regular stream.
        //

        ASSERT( FlagOn( Fcb->FcbState, FCB_STATE_MCB_INITIALIZED ));

        Result = FsRtlLookupLargeMcbEntry( &Fcb->Mcb,
                                           LlSectorsFromBytes( Vcb, FileOffset ),
                                           &LocalPsn.QuadPart,
                                           &LocalSectorCount.QuadPart,
                                           NULL,
                                           NULL,
                                           NULL );
    }

    //
    //  If within the Mcb then we use the data out of this entry and are nearly done.
    //

    if (Result) {

        if ( LocalPsn.QuadPart == -1 ) {

            //
            //  Regular files can have holey allocations which represent unrecorded extents.  For
            //  such extents which are sandwiched in between recorded extents of the file, the Mcb
            //  package tells us that it found a valid mapping but that it doesn't correspond to
            //  any extents on the media yet.  In this case, simply fake the disk offset.  The
            //  returned sector count is accurate.
            //

            *DiskOffset = 0;

            Recorded = FALSE;

        } else {

            //
            //  Now mimic the effects of physical sector sparing.  This may shrink the size of the
            //  returned run if sparing interrupted the extent on disc.
            //

            ASSERT( LocalPsn.HighPart == 0 );

            if (Vcb->Pcb->SparingMcb) {

                LONGLONG SparingPsn;
                LONGLONG SparingSectorCount;

                if (FsRtlLookupLargeMcbEntry( Vcb->Pcb->SparingMcb,
                                              LocalPsn.LowPart,
                                              &SparingPsn,
                                              &SparingSectorCount,
                                              NULL,
                                              NULL,
                                              NULL )) {

                    //
                    //  Only emit noise if we will really change anything as a result
                    //  of the sparing table.
                    //

                    if (SparingPsn != -1 ||
                        SparingSectorCount < LocalSectorCount.QuadPart) {

                        DebugTrace(( 0, Dbg, "UdfLookupAllocation, spared [%x, +%x) onto [%x, +%x)\n",
                                             LocalPsn.LowPart,
                                             LocalSectorCount.LowPart,
                                             (ULONG) SparingPsn,
                                             (ULONG) SparingSectorCount ));
                    }

                    //
                    //  If we did not land in a hole, map the sector.
                    //

                    if (SparingPsn != -1) {

                        LocalPsn.QuadPart = SparingPsn;
                    }

                    //
                    //  The returned sector count now reduces the previous sector count.
                    //  If we landed in a hole, this indicates that the trailing edge of
                    //  the extent is spared, if not this indicates that the leading
                    //  edge is spared.
                    //

                    if (SparingSectorCount < LocalSectorCount.QuadPart) {

                        LocalSectorCount.QuadPart = SparingSectorCount;
                    }
                }
            }

            *DiskOffset = LlBytesFromSectors( Vcb, LocalPsn.QuadPart ) + SectorOffset( Vcb, FileOffset );

            //
            //  Now we can apply method 2 fixups, which will again interrupt the size of the extent.
            //

            if (FlagOn( Vcb->VcbState, VCB_STATE_METHOD_2_FIXUP )) {

                LARGE_INTEGER SectorsToRunout;

                SectorsToRunout.QuadPart= UdfMethod2NextRunoutInSectors( Vcb, *DiskOffset );

                if (SectorsToRunout.QuadPart < LocalSectorCount.QuadPart) {

                    LocalSectorCount.QuadPart = SectorsToRunout.QuadPart;
                }

                *DiskOffset = UdfMethod2TransformByteOffset( Vcb, *DiskOffset );
            }
        }

    } else {

        //
        //  We know that prior to this call the system has restricted IO to points within the
        //  the file data.  Since we failed to find a mapping this is an unrecorded extent at
        //  the end of the file, so just conjure up a proper representation.
        //

        ASSERT( FileOffset < Fcb->FileSize.QuadPart );

        *DiskOffset = 0;

        LocalSectorCount.QuadPart = LlSectorsFromBytes( Vcb, Fcb->FileSize.QuadPart ) -
                                    LlSectorsFromBytes( Vcb, FileOffset ) +
                                    1;

        Recorded = FALSE;
    }

    //
    //  Restrict to MAXULONG bytes of allocation
    //

    if (LocalSectorCount.QuadPart > SectorsFromBytes( Vcb, MAXULONG )) {

        *ByteCount = MAXULONG;

    } else {

        *ByteCount = BytesFromSectors( Vcb, LocalSectorCount.LowPart );
    }

    *ByteCount -= SectorOffset( Vcb, FileOffset );

    return Recorded;
}
Example #3
0
NTSTATUS
UdfDvdReadStructure (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp,
    IN PFCB Fcb

    )

/*++

Routine Description:

    This routine handles the special form of the Dvd structure reading IOCTLs
    performed in the context of a file.  For these IOCTLs, the incoming parameter
    is in file-relative form, which must be translated to a device-relatvie form
    before it can continue.

Arguments:

    Irp - Supplies the Irp to process
    
    Fcb - Supplies the file being operated with

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status = STATUS_INVALID_PARAMETER;
    PDVD_READ_STRUCTURE ReadStructure;

    LARGE_INTEGER Offset;
    BOOLEAN Result;

    PIO_STACK_LOCATION IrpSp;
    
    //
    //  Grab the input buffer and confirm basic validity.
    //
    
    IrpSp = IoGetCurrentIrpStackLocation( Irp );
    ReadStructure = (PDVD_READ_STRUCTURE) Irp->AssociatedIrp.SystemBuffer;

    if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(DVD_READ_STRUCTURE)) {

        UdfCompleteRequest( IrpContext, Irp, Status );
        return Status;
    }

    //
    //  Now, convert the file byte offset in the structure to a physical sector.
    //

    Result = FsRtlLookupLargeMcbEntry( &Fcb->Mcb,
                                       LlSectorsFromBytes( Fcb->Vcb, ReadStructure->BlockByteOffset.QuadPart ),
                                       &Offset.QuadPart,
                                       NULL,
                                       NULL,
                                       NULL,
                                       NULL );

    //
    //  If we failed the lookup, we know that this must be some form of unrecorded
    //  extent on the media.  This IOCTL is ill-defined at this point, so we have
    //  to give up.
    //
    
    if (!Result || Offset.QuadPart == -1) {
        
        UdfCompleteRequest( IrpContext, Irp, Status );
        return Status;
    }
    
    //
    //  The input is buffered from user space, so we know we can just rewrite it.
    //

    ReadStructure->BlockByteOffset.QuadPart = LlBytesFromSectors( Fcb->Vcb, Offset.QuadPart );

    //
    //  Copy the arguments and set up the completion routine
    //

    IoCopyCurrentIrpStackLocationToNext( Irp );

    IoSetCompletionRoutine( Irp,
                            UdfDevCtrlCompletionRoutine,
                            NULL,
                            TRUE,
                            TRUE,
                            TRUE );

    //
    //  Send the request.
    //

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

    //
    //  Cleanup our Irp Context.  The driver has completed the Irp.
    //

    UdfCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );

    return Status;
}