fatdent.cxx

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

CXX
1,176
字号
/*++

Copyright (c) 1991-2000 Microsoft Corporation

Module Name:

    fatdent.cxx

--*/

#include <pch.cxx>

#define _UFAT_MEMBER_
#include "ufat.hxx"

#include "error.hxx"
#include "ifssys.hxx"
#include "wstring.hxx"

// TimeInfo is full of windows stuff.
#if !defined( _AUTOCHECK_ ) && !defined( _SETUP_LOADER_ ) && !defined( _EFICHECK_ )

#include "timeinfo.hxx"

#endif


DEFINE_EXPORTED_CONSTRUCTOR( FAT_DIRENT, OBJECT, UFAT_EXPORT );

VOID
FAT_DIRENT::Construct (
        )
/*++

Routine Description:

    Constructor for FAT_DIRENT.

Arguments:

    None.

Return Value:

    None.

--*/
{
    _dirent = NULL;
}


UFAT_EXPORT
FAT_DIRENT::~FAT_DIRENT(
    )
/*++

Routine Description:

    Destructor for FAT_DIRENT.

Arguments:

    None.

Return Value:

    None.

--*/
{
    Destroy();
}


UFAT_EXPORT
BOOLEAN
FAT_DIRENT::Initialize(
    IN OUT  PVOID   Dirent
    )
/*++

Routine Description:

    This routine initializes the object to use the directory entry
    pointed to by Dirent.

Arguments:

    Dirent  - Supplies the directory entry.

Return Value:

    FALSE   - Failure.
    TRUE    - Success.

--*/
{
    _dirent = (PUCHAR) Dirent;
    _FatType = FAT_TYPE_UNKNOWN;
    return _dirent ? TRUE : FALSE;
}


UFAT_EXPORT
BOOLEAN
FAT_DIRENT::Initialize(
    IN OUT  PVOID   Dirent,
    IN      UCHAR   FatType
    )
/*++

Routine Description:

    This routine initializes the object to use the directory entry
    pointed to by Dirent.

Arguments:

    Dirent  - Supplies the directory entry.
    FatType - Supplies the FAT type.

Return Value:

    FALSE   - Failure.
    TRUE    - Success.

--*/
{
    _dirent = (PUCHAR) Dirent;
    _FatType = FatType;
    return _dirent ? TRUE : FALSE;
}

UFAT_EXPORT
BOOLEAN
FAT_DIRENT::QueryName(
    OUT PWSTRING    Name
    ) CONST
/*++

Routine Description:

    This routine copies the directory entries name to 'Name' in an
    appropriate format.

    Directories and files will be returned in compressed 8.3 format.
    Labels will be returned in compressed 11 character format.

Arguments:

    Name    - Returns the name of the directory entry in the appropriate
              format.

Return Value:

    None.

--*/
{
    LONG    i;
    STR     buf[80];
    DSTRING tmp_string;
    DSTRING tmp2;
    CHNUM   l;

    if (!_dirent) {
        return Name->Initialize();
    }

    if (IsVolumeLabel()) {
        memcpy(buf, _dirent, 11);
        buf[11] = 0;

        if (buf[0] == 0x05) {
            buf[0] = (UCHAR)0xE5;
        }

        if (!tmp_string.Initialize(buf))
            return FALSE;

        l = tmp_string.QueryChCount();

        for (i = l - 1; i >= 0 && tmp_string.QueryChAt(i) == ' '; i--) {
        }

        return Name->Initialize(&tmp_string, 0, i + 1);
    }

    memcpy(buf, _dirent, 8);
    buf[8] = 0;

    if (buf[0] == 0x05) {
        buf[0] = (UCHAR)0xE5;
    }

    if (!tmp_string.Initialize(buf))
        return FALSE;

    if (Is8LowerCase()) {
        tmp_string.Strlwr(0);
    }

    l = tmp_string.QueryChCount();

    // Remove trailing white spaces
    for (i = l - 1; i >= 0 && tmp_string.QueryChAt(i) == ' '; i--) {
    }

    if (!Name->Initialize(&tmp_string, 0, i + 1))
        return FALSE;

    memcpy(buf, &_dirent[8], 3);
    buf[3] = 0;

    if (!tmp_string.Initialize(buf))
        return FALSE;

    if (Is3LowerCase()) {
        tmp_string.Strlwr(0);
    }

    l = tmp_string.QueryChCount();

    for (i = l - 1; i >= 0 && tmp_string.QueryChAt(i) == ' '; i--) {
    }

    if (i + 1) {
        if (!tmp2.Initialize(".") ||
            !Name->Strcat(&tmp2) ||
            !tmp2.Initialize(&tmp_string, 0, i + 1) ||
            !Name->Strcat(&tmp2))
            return FALSE;
    }
    return TRUE;
}

extern VOID DoInsufMemory(VOID);

BOOLEAN
FAT_DIRENT::SetName(
    IN  PCWSTRING   Name
    )
/*++

Routine Description:

    This routine expects a "compressed" null-terminated name in a format
    compatible with the return value of 'QueryName'.

    The validity of the characters in the name will not be checked
    by this routine.  Only that the name has the appropriate
    structure.  The routine "IsValidName" will check the validity
    of the name characters.

Arguments:

    Name    - Supplies the new name for the directory entry.

Return Value:

    FALSE   - The name was invalid.
    TRUE    - The name was successfully set.

--*/
{
    CHNUM   i, j;
    STR     buf[40];
    CHNUM   l;
    DSTRING tmp_string;

    if (IsVolumeLabel()) {
       if (!Name->QuerySTR( 0, TO_END, buf, 40) ||
           (i = strlen(buf)) > 11) {
          return FALSE;
       }

       if (!FAT_SA::IsValidString(Name)) {
          return FALSE;
       }

       memset(&_dirent[i], ' ', (UINT) (11 - i));
       memcpy(_dirent, buf, (UINT) i);

       if (_dirent[0] == 0xE5) {
          _dirent[0] = 0x05;
       }

       return TRUE;
    }

    l = Name->QueryChCount();

    if (Name->QueryChAt(0) == '.' && l == 1) {
        memcpy(_dirent, ".          ", 11);
        return TRUE;
    } else if (Name->QueryChAt(0) == '.' &&
               Name->QueryChAt(1) == '.' &&
               l == 2) {
        memcpy(_dirent, "..         ", 11);
        return TRUE;
    }

    for (i = 0; i < l && Name->QueryChAt(i) != '.'; i++) {
    }

    if (!tmp_string.Initialize(Name, 0, i)) {
    DoInsufMemory();
        return FALSE;
    }

    if (!tmp_string.QuerySTR( 0, TO_END, buf, 40)) {
        return FALSE;
    }

    if ((j = strlen(buf)) > 8) {
        return FALSE;
    }

    memset(&buf[j], ' ', (UINT) (11 - j));
    if (i < l) {
        for (j = i + 1; j < l && Name->QueryChAt(j) != '.'; j++) {
        }

        if (j < l) {
            return FALSE;
        }

        if (i + 1 < l) {
            if (!tmp_string.Initialize(Name, i + 1)) {
        DoInsufMemory();
                return FALSE;
            }

        if (!tmp_string.QuerySTR( 0, TO_END, &buf[8], 32)) {
                return FALSE;
            }

            if ((j = strlen(buf)) > 11) {
                return FALSE;
            }

            memset(&buf[j], ' ', (UINT) (11 - j));
        }
    }

    memcpy(_dirent, buf, 11);

    if (_dirent[0] == 0xE5) {
        _dirent[0] = 0x05;
    }

    return TRUE;
}


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

Routine Description:

    This routine verifies that the name is composed of valid
    characters.

Arguments:

    None.

Return Value:

    FALSE   - The name is not valid.
    TRUE    - The name is valid.

--*/
{
    DSTRING tmp;
    STR     buf[40];

    if (!_dirent) {
    perrstk->push(ERR_NOT_INIT, QueryClassId());
        return FALSE;
    }

    if (IsDot() || IsDotDot()) {
        return IsDirectory();
    }

    memcpy(buf, _dirent, 11);
    buf[11] = 0;

    if (buf[0] == 0x05) {
        buf[0] = (UCHAR)0xE5;
    }

    if (!tmp.Initialize(buf)) {
        return FALSE;
    }

    return FAT_SA::IsValidString(&tmp);
}


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

Routine Description:

    This routine verifies the validity of the last write time.

Arguments:

    None.

Return Value:

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

--*/
{
    USHORT  t;
    USHORT  d;

    DebugAssert(_dirent);

    memcpy(&t, &_dirent[22], sizeof(USHORT)); // time field
    memcpy(&d, &_dirent[24], sizeof(USHORT)); // date field

    return TimeStampsAreValid(t, d);
}

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

Routine Description:

    This routine returns the last write 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 );

    memcpy(&t, &_dirent[22], sizeof(USHORT)); // time field
    memcpy(&d, &_dirent[24], 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::SetLastWriteTime(
    )
/*++

Routine Description:

    This routine sets the last write 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[22], &fat_time, sizeof(USHORT));
    memcpy(&_dirent[24], &fat_date, sizeof(USHORT));

    return TRUE;
}

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

Routine Description:

    This routine verifies the validity of the creation time.

Arguments:

    None.

Return Value:

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

--*/
{
    USHORT  t;
    USHORT  d;

    DebugAssert(_dirent);

    memcpy(&t, &_dirent[14], sizeof(USHORT)); // time field
    memcpy(&d, &_dirent[16], sizeof(USHORT)); // date field

    return TimeStampsAreValid(t, d);

}

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

Routine Description:

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

⌨️ 快捷键说明

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