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

📄 pathsup.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (c) 1989-2000 Microsoft Corporation

Module Name:

    PathSup.c

Abstract:

    This module implements the Path Table support routines for Cdfs.

    The path table on a CDROM is a condensed summary of the entire
    directory structure.  It is stored on a number of contiguous sectors
    on the disk.  Each directory on the disk has an entry in the path
    table.  The entries are aligned on USHORT boundaries and MAY span
    sector boundaries.  The entries are stored as a breadth-first search.

    The first entry in the table contains the entry for the root.  The
    next entries will consist of the contents of the root directory.  The
    next entries will consist of the all the directories at the next level
    of the tree.  The children of a given directory will be grouped together.

    The directories are assigned ordinal numbers based on their position in
    the path table.  The root dirctory is assigned ordinal value 1.

    Path table sectors:

      Ordinal     1        2        3             4       5        6
                                         +-----------+
                                         | Spanning  |
                                         | Sectors   |
              +----------------------------+  +------------------------+
              |        |        |        | |  |      |         |       |
      DirName |  \     |   a    |    b   |c|  |   c  |    d    |   e   |
              |        |        |        | |  |      |         |       |
      Parent #|  1     |   1    |    1   | |  |   2  |    2    |   3   |
              +----------------------------+  +------------------------+

    Directory Tree:

                                            \ (root)

                                          /   \
                                         /     \
                                        a       b

                                      /   \       \
                                     /     \       \
                                    c       d       e

    Path Table Entries:

        - Position scan at known offset in the path table.  Path Entry at
            this offset must exist and is known to be valid.  Used when
            scanning for the children of a given directory.

        - Position scan at known offset in the path table.  Path Entry is
            known to start at this location but the bounds must be checked
            for validity.

        - Move to next path entry in the table.

        - Update a common path entry structure with the details of the
            on-disk structure.  This is used to smooth out the differences
            in the on-disk structures.

        - Update the filename in the in-memory path entry with the bytes
            off the disk.  For Joliet disks we will have
            to convert to little endian.  We assume that directories
            don't have version numbers.


--*/

#include "CdProcs.h"

//
//  The Bug check file id for this module
//

#define BugCheckFileId                   (CDFS_BUG_CHECK_PATHSUP)

//
//  Local macros
//

//
//  PRAW_PATH_ENTRY
//  CdRawPathEntry (
//      IN PIRP_CONTEXT IrpContext,
//      IN PPATH_ENUM_CONTEXT PathContext
//      );
//

#define CdRawPathEntry(IC, PC)      \
    Add2Ptr( (PC)->Data, (PC)->DataOffset, PRAW_PATH_ENTRY )

//
//  Local support routines
//

VOID
CdMapPathTableBlock (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB Fcb,
    IN LONGLONG BaseOffset,
    IN OUT PPATH_ENUM_CONTEXT PathContext
    );

BOOLEAN
CdUpdatePathEntryFromRawPathEntry (
    IN PIRP_CONTEXT IrpContext,
    IN ULONG Ordinal,
    IN BOOLEAN VerifyBounds,
    IN PPATH_ENUM_CONTEXT PathContext,
    OUT PPATH_ENTRY PathEntry
    );

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, CdFindPathEntry)
#pragma alloc_text(PAGE, CdLookupPathEntry)
#pragma alloc_text(PAGE, CdLookupNextPathEntry)
#pragma alloc_text(PAGE, CdMapPathTableBlock)
#pragma alloc_text(PAGE, CdUpdatePathEntryFromRawPathEntry)
#pragma alloc_text(PAGE, CdUpdatePathEntryName)
#endif


VOID
CdLookupPathEntry (
    IN PIRP_CONTEXT IrpContext,
    IN ULONG PathEntryOffset,
    IN ULONG Ordinal,
    IN BOOLEAN VerifyBounds,
    IN OUT PCOMPOUND_PATH_ENTRY CompoundPathEntry
    )

/*++

Routine Description:

    This routine is called to initiate a walk through a path table.  We are
    looking for a path table entry at location PathEntryOffset.

Arguments:

    PathEntryOffset - This is our target point in the Path Table.  We know that
        a path entry must begin at this point although we may have to verify
        the bounds.

    Ordinal - Ordinal number for the directory at the PathEntryOffset above.

    VerifyBounds - Indicates whether we need to check the validity of
        this entry.

    CompoundPathEntry - PathEnumeration context and in-memory path entry.  This
        has been initialized outside of this call.

Return Value:

    None.

--*/

{
    PPATH_ENUM_CONTEXT PathContext = &CompoundPathEntry->PathContext;
    LONGLONG CurrentBaseOffset;

    PAGED_CODE();

    //
    //  Compute the starting base and starting path table offset.
    //

    CurrentBaseOffset = SectorTruncate( PathEntryOffset );

    //
    //  Map the next block in the Path Table.
    //

    CdMapPathTableBlock( IrpContext,
                         IrpContext->Vcb->PathTableFcb,
                         CurrentBaseOffset,
                         PathContext );

    //
    //  Set up our current offset into the Path Context.
    //

    PathContext->DataOffset = PathEntryOffset - PathContext->BaseOffset;

    //
    //  Update the in-memory structure for this path entry.
    //

    (VOID) CdUpdatePathEntryFromRawPathEntry( IrpContext,
                                              Ordinal,
                                              VerifyBounds,
                                              &CompoundPathEntry->PathContext,
                                              &CompoundPathEntry->PathEntry );
}


BOOLEAN
CdLookupNextPathEntry (
    IN PIRP_CONTEXT IrpContext,
    IN OUT PPATH_ENUM_CONTEXT PathContext,
    IN OUT PPATH_ENTRY PathEntry
    )

/*++

Routine Description:

    This routine is called to move to the next path table entry.  We know
    the offset and the length of the current entry.  We start by computing
    the offset of the next entry and determine if it is contained in the
    table.  Then we check to see if we need to move to the next sector in
    the path table.  We always map two sectors at a time so we don't
    have to deal with any path entries which span sectors.  We move to
    the next sector if we are in the second sector of the current mapped
    data block.

    We look up the next entry and update the path entry structure with
    the values out of the raw sector but don't update the CdName structure.

Arguments:

    PathContext - Enumeration context for this scan of the path table.

    PathEntry - In-memory representation of the on-disk path table entry.

Return Value:

    BOOLEAN - TRUE if another entry is found, FALSE otherwise.
        This routine may raise on error.

--*/

{
    LONGLONG CurrentBaseOffset;

    PAGED_CODE();

    //
    //  Get the offset of the next path entry within the current
    //  data block.
    //

    PathContext->DataOffset += PathEntry->PathEntryLength;

    //
    //  If we are in the last data block then check if we are beyond the
    //  end of the file.
    //

    if (PathContext->LastDataBlock) {

        if (PathContext->DataOffset >= PathContext->DataLength) {

            return FALSE;
        }

    //
    //  If we are not in the last data block of the path table and
    //  this offset is in the second sector then move to the next
    //  data block.
    //

    } else if (PathContext->DataOffset >= SECTOR_SIZE) {

        CurrentBaseOffset = PathContext->BaseOffset + SECTOR_SIZE;

        CdMapPathTableBlock( IrpContext,
                             IrpContext->Vcb->PathTableFcb,
                             CurrentBaseOffset,
                             PathContext );

        //
        //  Set up our current offset into the Path Context.
        //

        PathContext->DataOffset -= SECTOR_SIZE;
    }

    //
    //  Now update the path entry with the values from the on-disk
    //  structure.
    //
        
    return CdUpdatePathEntryFromRawPathEntry( IrpContext,
                                              PathEntry->Ordinal + 1,
                                              TRUE,
                                              PathContext,
                                              PathEntry );
}


BOOLEAN
CdFindPathEntry (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB ParentFcb,
    IN PCD_NAME DirName,
    IN BOOLEAN IgnoreCase,
    IN OUT PCOMPOUND_PATH_ENTRY CompoundPathEntry
    )

/*++

Routine Description:

    This routine will walk through the path table looking for a matching entry for DirName
    among the child directories of the ParentFcb.

Arguments:

    ParentFcb - This is the directory we are examining.  We know the ordinal and path table
        offset for this directory in the path table.  If this is the first scan for this
        Fcb we will update the first child offset for this directory in the path table.

    DirName - This is the name we are searching for.  This name will not contain wildcard
        characters.  The name will also not have a version string.

    IgnoreCase - Indicates if this search is exact or ignore case.

    CompoundPathEntry - Complete path table enumeration structure.  We will have initialized
        it for the search on entry.  This will be positioned at the matching name if found.

Return Value:

    BOOLEAN - TRUE if matching entry found, FALSE otherwise.

--*/

{
    BOOLEAN Found = FALSE;
    BOOLEAN UpdateChildOffset = TRUE;

    ULONG StartingOffset;
    ULONG StartingOrdinal;

    PAGED_CODE();

    //
    //  Position ourselves at either the first child or at the directory itself.
    //  Lock the Fcb to get this value and remember whether to update with the first
    //  child.
    //

    StartingOffset = CdQueryFidPathTableOffset( ParentFcb->FileId );
    StartingOrdinal = ParentFcb->Ordinal;

	//
	//  ISO 9660 9.4.4 restricts the backpointer from child to parent in a
	//  pathtable entry to 16bits. Although we internally store ordinals
	//  as 32bit values, it is impossible to search for the children of a
	//  directory whose ordinal value is greater than MAXUSHORT. Media that
	//  could induce such a search is illegal.
	//
	//  Note that it is not illegal to have more than MAXUSHORT directories.
	//

	if (ParentFcb->Ordinal > MAXUSHORT) {

		CdRaiseStatus( IrpContext, STATUS_DISK_CORRUPT_ERROR );
	}

    CdLockFcb( IrpContext, ParentFcb );

    if (ParentFcb->ChildPathTableOffset != 0) {

        StartingOffset = ParentFcb->ChildPathTableOffset;
        StartingOrdinal = ParentFcb->ChildOrdinal;
        UpdateChildOffset = FALSE;

    } else if (ParentFcb == ParentFcb->Vcb->RootIndexFcb) {

        UpdateChildOffset = FALSE;
    }

    CdUnlockFcb( IrpContext, ParentFcb );

    CdLookupPathEntry( IrpContext, StartingOffset, StartingOrdinal, FALSE, CompoundPathEntry );

    //
    //  Loop until we find a match or are beyond the children for this directory.
    //

    do {

        //
        //  If we are beyond this directory then return FALSE.
        //

        if (CompoundPathEntry->PathEntry.ParentOrdinal > ParentFcb->Ordinal) {

            //
            //  Update the Fcb with the offsets for the children in the path table.
            //

            if (UpdateChildOffset) {

                CdLockFcb( IrpContext, ParentFcb );

                ParentFcb->ChildPathTableOffset = StartingOffset;
                ParentFcb->ChildOrdinal = StartingOrdinal;

                CdUnlockFcb( IrpContext, ParentFcb );
            }

            break;
        }

        //
        //  If we are within the children of this directory then check for a match.
        //

        if (CompoundPathEntry->PathEntry.ParentOrdinal == ParentFcb->Ordinal) {

            //
            //  Update the child offset if not yet done.
            //

            if (UpdateChildOffset) {

                CdLockFcb( IrpContext, ParentFcb );

                ParentFcb->ChildPathTableOffset = CompoundPathEntry->PathEntry.PathTableOffset;
                ParentFcb->ChildOrdinal = CompoundPathEntry->PathEntry.Ordinal;

                CdUnlockFcb( IrpContext, ParentFcb );

                UpdateChildOffset = FALSE;
            }

            //
            //  Update the name in the path entry.
            //

            CdUpdatePathEntryName( IrpContext, &CompoundPathEntry->PathEntry, IgnoreCase );

            //
            //  Now compare the names for an exact match.
            //

            if (CdIsNameInExpression( IrpContext,
                                      &CompoundPathEntry->PathEntry.CdCaseDirName,
                                      DirName,
                                      0,
                                      FALSE )) {

                //
                //  Let our caller know we have a match.
                //

                Found = TRUE;
                break;
            }
        }

        //
        //  Go to the next entry in the path table.  Remember the current position
        //  in the event we update the Fcb.
        //

        StartingOffset = CompoundPathEntry->PathEntry.PathTableOffset;
        StartingOrdinal = CompoundPathEntry->PathEntry.Ordinal;

    } while (CdLookupNextPathEntry( IrpContext,
                                    &CompoundPathEntry->PathContext,
                                    &CompoundPathEntry->PathEntry ));

    return Found;
}


//
//  Local support routine
//

VOID
CdMapPathTableBlock (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB Fcb,
    IN LONGLONG BaseOffset,
    IN OUT PPATH_ENUM_CONTEXT PathContext
    )

/*++

Routine Description:

    This routine is called to map (or allocate and copy) the next
    data block in the path table.  We check if the next block will
    span a view boundary and allocate an auxilary buffer in that case.

Arguments:

⌨️ 快捷键说明

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