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

📄 fatsachk.cxx

📁 EFI(Extensible Firmware Interface)是下一代BIOS
💻 CXX
📖 第 1 页 / 共 5 页
字号:

    if (need_write) {
        if (FixLevel != CheckOnly && !easet.Write()) {
            return 0;
        }
    }

    return EaInfo->LastCn;
}


BOOLEAN
FAT_SA::EaSort(
    IN OUT  PEA_INFO    EaInfos,
    IN      ULONG       NumEas,
    IN OUT  PMESSAGE    Message,
    IN OUT  PBOOLEAN    NeedErrorsMessage
    )
/*++

Routine Description:

    This routine sorts the EaInfos array by 'OwnHandle' into ascending order.
    It also edits the FAT with the changes in the EAs order.

Arguments:

    EaInfos             - Supplies the array of EA_INFOs to sort.
    NumEas              - Supplies the number of elements in the array.
    Message             - Supplies an outlet for messages.
    NeedErrorsMessage   - Supplies whether or not errors have occurred
                            under check only conditions.

Return Value:

    FALSE   - Failure.
    TRUE    - Success.

--*/
{
    BOOLEAN done;
    EA_INFO tmp;
    ULONG   clus;
    ULONG   i;
    BOOLEAN change;

    done = FALSE;
    change = FALSE;
    while (!done) {
        done = TRUE;
        for (i = 0; i < NumEas - 1; i++) {
            if (EaInfos[i].OwnHandle > EaInfos[i + 1].OwnHandle) {
                done = FALSE;

                clus = _fat->RemoveChain(EaInfos[i + 1].PreceedingCn,
                                         EaInfos[i + 1].LastCn);

                _fat->InsertChain(clus,
                                  EaInfos[i + 1].LastCn,
                                  EaInfos[i].PreceedingCn);

                EaInfos[i + 1].PreceedingCn = EaInfos[i].PreceedingCn;
                EaInfos[i].PreceedingCn = EaInfos[i + 1].LastCn;
                if (i + 2 < NumEas) {
                    EaInfos[i + 2].PreceedingCn = EaInfos[i].LastCn;
                }

                change = TRUE;

                tmp = EaInfos[i];
                EaInfos[i] = EaInfos[i + 1];
                EaInfos[i + 1] = tmp;
            }
        }
    }

    if (change) {
        dofmsg(Message, NeedErrorsMessage);
        Message->Set(MSG_CHK_UNORDERED_EA_SETS);
        Message->Display();
    }

    return TRUE;
}


BOOLEAN
FAT_SA::RebuildEaHeader(
    IN OUT  PULONG      StartingCluster,
    IN OUT  PEA_INFO    EaInfos,
    IN      ULONG       NumEas,
    IN OUT  PMEM        EaHeaderMem,
    OUT     PEA_HEADER  EaHeader,
    IN OUT  PBITVECTOR  FatBitMap,
    IN      FIX_LEVEL   FixLevel,
    IN OUT  PMESSAGE    Message,
    IN OUT  PBOOLEAN    NeedErrorsMessage
    )
/*++

Routine Description:

    This routine rebuilds the header and tables of the EA file base on the
    information in the 'EaInfos' array.  The header log is set to zero,
    and the header itself is relocated if any of the clusters are bad.

    The starting cluster may be relocated if there are bad clusters.

Arguments:

    StartingCluster     - Supplies the first cluster of the EA file.
    EaInfos             - Supplies an array containing information for every
                            EA set.
    NumberOfEas         - Supplies the total number of EA sets.
    EaHeaderMem         - Supplies the memory for the EA header.
    EaHeader            - Returns the EA header.
    FatBitMap           - Supplies the cross-links bitmap.
    FixLevel            - Supplies the CHKDSK fix level.
    Message             - Supplies an outlet for messages.
    NeedErrorsMessage   - Supplies whether or not errors have occurred
                            under check only conditions.

Return Value:

    FALSE   - Failure.
    TRUE    - Success.

--*/
{
    ULONG           length;
    ULONG           cluster_size;
    ULONG           actual_length;
    ULONG           new_chain;
    ULONG           last_cluster;
    BOOLEAN         changes;
    LONG            i, j, k;
    PEA_MAP_TBL     table;
    PEA_FILE_HEADER header;
    LONG            tmp;
    BOOLEAN         empty_ea_file;
    ULONG           clus;


    // Compute the number of clusters necessary for the header portion of
    // the EA file.

    length = sizeof(EA_FILE_HEADER) +
             BaseTableSize*sizeof(USHORT) +
             EaInfos[NumEas - 1].OwnHandle*sizeof(USHORT);

    cluster_size = _drive->QuerySectorSize()*QuerySectorsPerCluster();

    if (length%cluster_size) {
        length = length/cluster_size + 1;
    } else {
        length = length/cluster_size;
    }

    //
    // Make sure that the header contains enough clusters to accomodate
    // the size of the offset table.
    //

    last_cluster = EaInfos[0].PreceedingCn;

    actual_length = _fat->QueryLengthOfChain(*StartingCluster, last_cluster);

    if (length > actual_length) {

        dofmsg(Message, NeedErrorsMessage);
        Message->Set(MSG_CHK_NEED_MORE_HEADER_SPACE);
        Message->Display();

        new_chain = _fat->AllocChain((length - actual_length),
                                     &last_cluster);
        if (!new_chain) {
            Message->Set(MSG_CHK_INSUFFICIENT_DISK_SPACE);
            Message->Display();
            return FALSE;
        }

        if (IsCompressed() && !AllocSectorsForChain(new_chain)) {
            _fat->FreeChain(new_chain);
            Message->Set(MSG_CHK_INSUFFICIENT_DISK_SPACE);
            Message->Display();
            return FALSE;
        }

        for (clus = new_chain;
             !_fat->IsEndOfChain(clus);
             clus = _fat->QueryEntry(clus)) {

            FatBitMap->SetBit(clus);
        }
        FatBitMap->SetBit(clus);

        _fat->InsertChain(new_chain, last_cluster, EaInfos[0].PreceedingCn);

        EaInfos[0].PreceedingCn = last_cluster;

    } else if (length < actual_length) {

        dofmsg(Message, NeedErrorsMessage);
        Message->Set(MSG_CHK_UNUSED_EA_PORTION);
        Message->Display();

        last_cluster = _fat->QueryNthCluster(*StartingCluster,
                                             length - 1);

        clus = _fat->RemoveChain(last_cluster, EaInfos[0].PreceedingCn);

        EaInfos[0].PreceedingCn = last_cluster;

        for (;
             !_fat->IsEndOfChain(clus);
             clus = _fat->QueryEntry(clus)) {

            FatBitMap->ResetBit(clus);
        }
        FatBitMap->ResetBit(clus);

    }


    // Verify the cluster chain containing the header.

    changes = FALSE;
    if (FixLevel != CheckOnly &&
        !RecoverChain(StartingCluster, &changes, last_cluster, TRUE)) {

        dofmsg(Message, NeedErrorsMessage);
        Message->Set(MSG_CHK_INSUFFICIENT_DISK_SPACE);
        Message->Display();

        return FALSE;
    }

    if (changes) {
        dofmsg(Message, NeedErrorsMessage);
        Message->Set(MSG_CHK_RELOCATED_EA_HEADER);
        Message->Display();
    }


    // Compute the tables.

    if (!EaHeader->Initialize(EaHeaderMem, _drive, this, _fat,
                              *StartingCluster, (USHORT) length) ||
        !(table = EaHeader->GetMapTable()) ||
        !(header = EaHeader->GetEaFileHeader())) {

        Message->Set(MSG_CHK_NO_MEMORY);
        Message->Display();
        return FALSE;
    }

    if (!EaHeader->Read()) {
        if (FixLevel == CheckOnly) {
            dofmsg(Message, NeedErrorsMessage);
            Message->Set(MSG_CHK_RELOCATED_EA_HEADER);
            Message->Display();
        } else {
            return FALSE;
        }
    }


    // Set the log in the header to zero.

    header->Signature = HeaderSignature;
    header->FormatType = 0;
    header->LogType = 0;
    header->Cluster1 = 0;
    header->NewCValue1 = 0;
    header->Cluster2 = 0;
    header->NewCValue2 = 0;
    header->Cluster3 = 0;
    header->NewCValue3 = 0;
    header->Handle = 0;
    header->NewHOffset = 0;


    // Reconcile the tables with the EaInfo information.

    changes = FALSE;

    for (i = 0; i < BaseTableSize; i++) {
        table->BaseTab[i] = 0;
    }

    j = 0;
    empty_ea_file = TRUE;
    for (i = 0; i < (LONG) NumEas; i++) {

        if (EaInfos[i].UsedCount != 1) {
            continue;
        }

        empty_ea_file = FALSE;

        for (; j < (LONG) EaInfos[i].OwnHandle; j++) {
            if (table->OffTab[j] != InvalidHandle) {
                table->OffTab[j] = InvalidHandle;
                changes = TRUE;
            }
        }

        length = _fat->QueryLengthOfChain(*StartingCluster,
                                         EaInfos[i].PreceedingCn);

        for (k = j>>7; k >= 0 && !table->BaseTab[k]; k--) {
            table->BaseTab[k] = (USHORT) length;
        }

        tmp = length - table->BaseTab[j>>7];

        if ((LONG)table->OffTab[j] != tmp) {
            table->OffTab[j] = (USHORT) tmp;
            changes = TRUE;
        }

        j++;
    }

    if (empty_ea_file) {

        for (clus = *StartingCluster;
             !_fat->IsEndOfChain(clus);
             clus = _fat->QueryEntry(clus)) {

            FatBitMap->ResetBit(clus);

        }
        FatBitMap->ResetBit(clus);

        *StartingCluster = 0;

        return TRUE;
    }

    tmp = _fat->QueryLengthOfChain(*StartingCluster);
    for (k = ((j - 1)>>7) + 1; k < BaseTableSize; k++) {
        table->BaseTab[k] = (USHORT) tmp;
    }

    for (; j < (LONG) EaHeader->QueryOffTabSize(); j++) {
        if (table->OffTab[j] != InvalidHandle) {
            table->OffTab[j] = InvalidHandle;
            changes = TRUE;
        }
    }

    if (changes) {
        dofmsg(Message, NeedErrorsMessage);
        Message->Set(MSG_CHK_ERROR_IN_EA_HEADER);
        Message->Display();
    }

    return TRUE;
}


VOID
FreeSpaceInBitmap(
    IN      ULONG       StartingCluster,
    IN      PCFAT       Fat,
    IN OUT  PBITVECTOR  FatBitMap
    )
{
    if (!StartingCluster) {
        return;
    }

    while (!Fat->IsEndOfChain(StartingCluster)) {
        FatBitMap->ResetBit(StartingCluster);
        StartingCluster = Fat->QueryEntry(StartingCluster);
    }
    FatBitMap->ResetBit(StartingCluster);
}


ULONG
ComputeFileNameHashValue(
    IN  PVOID   FileName
    )
{
    ULONG   h;
    BYTE    i;
    PUCHAR  p;

    p = (PUCHAR) FileName;
    h = 0;
    for (i=0; i<11; i++) {
        h = (h << 2) ^ p[i];
    }
    for (i=0; i<2; i++) {
        h = (h << 2) ^ p[i];
    }
    return h;
}

STATIC ULONG         _Twinkle = 0;
STATIC LONG64        _LastTwnkTime = 0;
STATIC ULONG         _LastPercent = 0xFFFFFFFF;

BOOLEAN
DisplayTwnkPercent(
    ULONG   percent
    )
{
    BIG_INT currenttime;

#if !defined( _EFICHECK_ )
    NtQuerySystemTime((_LARGE_INTEGER *)&currenttime);
#else
    EfiQuerySystemTime((_LARGE_INTEGER *)&currenttime);
#endif
    // The above clock counts in 1/10,000ths of a second

    if((percent != _LastPercent) ||
       ((currenttime.GetQuadPart() - _LastTwnkTime) >= (6 * 100 * 10000)))
    {
        if(percent > 100) {
            percent = 100;
        }
        if((_Twinkle > 5) || _Verbose) {
            _Twinkle = 0;
        }
        if(_Verbose && (percent == _LastPercent)) {
            return TRUE;
        }
        _LastPercent = percent;
        _LastTwnkTime = currenttime.GetQuadPart();
        if(_pvfMessage) {
            STR  dots[6];

            dots[5] = '\0';
            dots[4] = ' ';
            dots[3] = ' ';
            dots[2] = ' ';
            dots[1] = ' ';
            dots[0] = ' ';
            switch(_Twinkle) {
                case 5:
                default:
                    dots[4] = '.';
                case 4:
                    dots[3] = '.';
                case 3:
                    dots[2] = '.';
                case 2:
                    dots[1] = '.';
                case 1:
                    dots[0] = '.';
                case 0:
                    ;
            }
            if(!_Verbose) {
                _Twinkle++;
            }
            _pvfMessage->Set(MSG_PERCENT_COMPLETE2);
            if (!_pvfMessage->Display("%d%s", percent, &dots[0])) {
                return FALSE;
            }
            if(_Verb

⌨️ 快捷键说明

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