fatdent.cxx

来自「EFI(Extensible Firmware Interface)是下一代BI」· CXX 代码 · 共 1,176 行 · 第 1/2 页

CXX
1,176
字号
Arguments:

    None.

Return Value:

    FALSE   - Failure.
    TRUE    - Success.

--*/
{
    TIME_FIELDS TimeFields;
    USHORT      t;
    USHORT      d;
    USHORT      msec;
    USHORT      year, month, day, hour, minute, second;

    DebugAssert( _dirent );
    DebugPtrAssert( TimeStamp );

    memcpy(&t, &_dirent[14], sizeof(USHORT)); // time field
    memcpy(&d, &_dirent[16], sizeof(USHORT)); // date field
    msec = _dirent[13] * 10;                  // msec field

    second  = (t&0x001F)*2;     // seconds
    minute  = (t&0x07E0)>>5;    // Minutes
    hour    = t>>11;            // Hours
    day     = d&0x001F;         // Day of month 1-31
    month   = (d&0x01E0)>>5;    // Month
    year    = (d>>9) + 1980;    // Year

    if (msec >= 1000) {
        second += 1;
        msec -= 1000;
    }

    TimeFields.Year         = year;
    TimeFields.Month        = month;
    TimeFields.Day          = day;
    TimeFields.Hour         = hour;
    TimeFields.Minute       = minute;
    TimeFields.Second       = second;
    TimeFields.Milliseconds = msec;

    return RtlTimeFieldsToTime( &TimeFields, (PTIME)TimeStamp );
}

BOOLEAN
FAT_DIRENT::SetCreationTime(
    )
/*++

Routine Description:

    This routine sets the creation time to the current date and time.

Arguments:

    None.

Return Value:

    FALSE   - Time stamp was not set successfully.
    TRUE    - Time stamp was set successfully.

--*/
{
    USHORT  fat_time;
    USHORT  fat_date;

    DebugAssert(_dirent);

    LARGE_INTEGER SystemTime, LocalTime;
    TIME_FIELDS Time;


#if !defined( _SETUP_LOADER_ )
    IFS_SYSTEM::QueryNtfsTime( &SystemTime );
    RtlSystemTimeToLocalTime( &SystemTime, &LocalTime );
#else
    IFS_SYSTEM::QueryNtfsTime( &LocalTime );
#endif

    RtlTimeToTimeFields(&LocalTime, &Time);

    fat_time = Time.Second/2;
    fat_time |= Time.Minute<<5;
    fat_time |= Time.Hour<<11;

    fat_date = Time.Day;
    fat_date |= Time.Month<<5;
    fat_date |= (Time.Year - 1980)<<9;

    memcpy(&_dirent[14], &fat_time, sizeof(USHORT));
    memcpy(&_dirent[16], &fat_date, sizeof(USHORT));

    return TRUE;
}

UFAT_EXPORT
BOOLEAN
FAT_DIRENT::IsValidLastAccessTime(
    ) CONST
/*++

Routine Description:

    This routine verifies the validity of the last access time.

Arguments:

    None.

Return Value:

    FALSE   - Invalid time stamp.
    TRUE    - Valid time stamp.

--*/
{
    USHORT  t = 0;
    USHORT  d;

    DebugAssert(_dirent);

    memcpy(&d, &_dirent[18], sizeof(USHORT)); // date field

    return TimeStampsAreValid(t, d);
}

UFAT_EXPORT
BOOLEAN
FAT_DIRENT::QueryLastAccessTime(
    OUT LARGE_INTEGER   *TimeStamp
    ) CONST
/*++

Routine Description:

    This routine returns the last access time in the form of a time fields
    structure.

Arguments:

    None.

Return Value:

    FALSE   - Failure.
    TRUE    - Success.

--*/
{

    TIME_FIELDS TimeFields;
    USHORT      t;
    USHORT      d;
    USHORT      year, month, day, hour, minute, second;

    DebugAssert( _dirent );
    DebugPtrAssert( TimeStamp );

    t = 0;                                    // no time for last access; just date
    memcpy(&d, &_dirent[18], sizeof(USHORT)); // date field

    second  = (t&0x001F)*2;     // seconds
    minute  = (t&0x07E0)>>5;    // Minutes
    hour    = t>>11;            // Hours
    day     = d&0x001F;         // Day of month 1-31
    month   = (d&0x01E0)>>5;    // Month
    year    = (d>>9) + 1980;    // Year

    TimeFields.Year         = year;
    TimeFields.Month        = month;
    TimeFields.Day          = day;
    TimeFields.Hour         = hour;
    TimeFields.Minute       = minute;
    TimeFields.Second       = second;
    TimeFields.Milliseconds = 0;

    return RtlTimeFieldsToTime( &TimeFields, (PTIME)TimeStamp );
}

BOOLEAN
FAT_DIRENT::SetLastAccessTime(
    )
/*++

Routine Description:

    This routine sets the last access time to the current date and time.

Arguments:

    None.

Return Value:

    FALSE   - Time stamp was not set successfully.
    TRUE    - Time stamp was set successfully.

--*/
{
    USHORT  fat_date;

    DebugAssert(_dirent);

    LARGE_INTEGER SystemTime, LocalTime;
    TIME_FIELDS Time;


#if !defined( _SETUP_LOADER_ )
    IFS_SYSTEM::QueryNtfsTime( &SystemTime );
    RtlSystemTimeToLocalTime( &SystemTime, &LocalTime );
#else
    IFS_SYSTEM::QueryNtfsTime( &LocalTime );
#endif

    RtlTimeToTimeFields(&LocalTime, &Time);

    fat_date = Time.Day;
    fat_date |= Time.Month<<5;
    fat_date |= (Time.Year - 1980)<<9;

    memcpy(&_dirent[18], &fat_date, sizeof(USHORT));

    return TRUE;
}

VOID
FAT_DIRENT::Destroy(
    )
/*++

Routine Description:

    This routine returns the object to its initial state.

Arguments:

    None.

Return Value:

    None.

--*/
{
    _dirent = NULL;
}

UCHAR
RotateCharRight(
    IN  UCHAR   Char,
    IN  INT     Shift
    )
/*++

Routine Description:

    This function rotates an eight-bit character right by the
    specified number of bits.

Arguments:

    Char    --  Supplies the character to rotate
    Shift   --  Supplies the number of bits to shift

Return Value:

    The rotated character.

--*/
{
    UCHAR low_bit;

    Shift %= 8;

    while( Shift-- ) {

        low_bit = Char & 1;
        Char >>= 1;
        if( low_bit ) {
            Char |= 0x80;
        }
    }

    return (UCHAR)Char;
}

UCHAR
FAT_DIRENT::QueryChecksum(
    ) CONST

/*++

Routine Description:

    This method gets the checksum from the directory entry.  If
    the entry is a short entry, the checksum is computed; if the
    entry is long, the checksum field is returned.

Arguments:

    None.

Return Value:

    The directory entry's checksum.

--*/
{
    int name_length;
    UCHAR sum;
    PUCHAR name;

    if( IsLongEntry() ) {

        return( _dirent[13] );

    } else {

        sum = 0;
        name = _dirent;
        for( name_length = 11; name_length != 0; name_length-- ) {

            sum = RotateCharRight(sum, 1) + *name++;
        }

        return( sum );
    }
}

BOOLEAN
FAT_DIRENT::IsWellTerminatedLongNameEntry(
    ) CONST
/*++

Routine Description:

    This method determines whether the entry is a well-terminated
    long-name entry.  A long-name entry is well terminated if:


--*/
{
    ULONG   i;
    WCHAR   Name[13];

    if( IsErased() || !IsLongNameEntry() ) {

        return FALSE;
    }

    // Assemble the bits and pieces of the name:
    //
    memcpy( &Name[0], &_dirent[1], 10 );
    memcpy( &Name[5], &_dirent[14], 12 );
    memcpy( &Name[11], &_dirent[28], 4 );

    if( IsLastLongEntry() ) {

        //
        // Valid syntax for the last name entry is:
        //
        //     N* {0 0xFFFF*}
        //
        // where N is the set of non-null characters.
        //
        for( i = 0; i < 13; i++ ) {

            if( Name[i] == 0 ) {

                break;
            }
        }

        if( i < 13 ) {

            //
            // We hit a null character--step over it.
            //
            i++;
        }

        //
        // The rest of the name-component must be 0xFFFF.
        //
        for( ; i < 13; i++ ) {

            if( Name[i] != 0xFFFF ) {

                return FALSE;
            }
        }

        // This name-component was accepted.
        //
        return TRUE;

    } else {

#if 0
        // This is an additional consistency check that
        // could be performed; however, now (as of 3/28/94)
        // the file-system doesn't care, so neither do we.

        // This is not the last component of the name, so
        // it can't have any NULL's in it.
        //
        for( i = 0; i < 13; i++ ) {

            if( Name[i] == 0 ) {

                return FALSE;
            }
        }
#endif

        return TRUE;
    }
}

BOOLEAN
FAT_DIRENT::QueryLongNameComponent(
    OUT PWSTRING    NameComponent
    ) CONST
/*++

Routine Description:

    This method extracts the long-name component from a Long Name
    Directory Entry.

Arguments:

    NameComponent   --  Receives the long-name component

Return Value:

    TRUE upon successful completion.

--*/
{
    ULONG   i;
    WCHAR   Name[13];

    if( IsErased() || !IsLongNameEntry() ) {

        return FALSE;
    }

    // Assemble the bits and pieces of the name:
    //
    memcpy( &Name[0], &_dirent[1], 10 );
    memcpy( &Name[5], &_dirent[14], 12 );
    memcpy( &Name[11], &_dirent[28], 4 );

    // Long names may be zero terminated; however, if the
    // name fits exactly into n long entries will not be
    // zero terminated.
    //
    for( i = 0; i < 13 && Name[i]; i++ );

    return( NameComponent->Initialize( Name, i ) );
}

BOOLEAN
FAT_DIRENT::NameHasTilde(
    ) CONST
/*++

Routine Description:

    This routine checks a short name entry to see if it contains a tilde.

Arguments:

    None.

Return Value:

    TRUE                        - Tilde.
    FALSE                       - No tilde.

--*/
{
    USHORT i;

    if (IsErased() || IsLongNameEntry()) {
        return FALSE;
    }

    for (i = 0; i < 11; ++i) {
        if ('~' == _dirent[i]) {
            return TRUE;
        }
    }
    return FALSE;
}

BOOLEAN
FAT_DIRENT::NameHasExtendedChars(
    ) CONST
/*++

Routine Description:

    This routine determines whether there are any extended chars
    (those with value >= 0x80) in the short file name.

Arguments:

    None.

Return Value:

    TRUE    - There are one or more extended chars.
    FALSE   - There are no extended chars.

--*/
{
    USHORT i;

    if (IsErased() || IsLongNameEntry()) {
        return FALSE;
    }

    for (i = 0; i < 11; ++i) {
        if (_dirent[i] >= 0x80) {
            return TRUE;
        }
    }
    return FALSE;
}

BOOLEAN
FAT_DIRENT::TimeStampsAreValid(
    USHORT t,
    USHORT d
    ) CONST
/*++

Routine Description:

    This routine examines the given time and date fields and
    determines whether they represent valid dates.

Arguments:

    None.

Return Value:

    TRUE    - The time and date are valid.
    FALSE   - One or both are invalid.

--*/
{
    USHORT  tmp;
    tmp = t&0x001F;         // 2-second increments
    if (tmp > 29) {
        return FALSE;
    }

    tmp = (t&0x07E0)>>5;    // Minutes
    if (tmp > 59) {
        return FALSE;
    }

    tmp = (t&0xF800)>>11;   // Hours
    if (tmp > 23) {
        return FALSE;
    }

    tmp = d&0x001F;         // Day of month
    if (tmp < 1 || tmp > 31) {
        return FALSE;
    }

    tmp = (d&0x01E0)>>5;    // Month
    if (tmp < 1 || tmp > 12) {
        return FALSE;
    }

    return TRUE;
}

⌨️ 快捷键说明

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