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

📄 fatsachk.cxx

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

    Report - Supplies the fat chkdsk report structure for storing
             the fix status.

    FatBitMap - Supplies a pointer to the bit map for cross-link
                detection.

    Message - Supplies an outlet for messages.

Return Values:

    TRUE  - Success.
    FALSE - Failed.

--*/
{

    SECRUN  root_secrun; // Allocate one cluster for the
                         // new root directory.
    ULONG   root_clus;   // New cluster number of the
                         // root directory
    ULONG   cluster_size;// Number of sectors in a cluster.

    ULONG   starting_data_lbn;
    ULONG   sector_size;

    starting_data_lbn = QueryStartDataLbn();
    cluster_size = QuerySectorsPerCluster();
    sector_size = _drive->QuerySectorSize();


    for (;;) {

        root_clus = _fat->AllocChain(1, NULL);

        if (!root_clus) {
            //
            // The disk is full, we have no choice but to bail out.
            //
            Message->Set(MSG_CHK_INSUFFICIENT_DISK_SPACE);
            Message->Display();
            return FALSE;
        }

        if ( !_hmem_F32->Initialize() ||
             !root_secrun.Initialize( _hmem_F32,
                                      _drive,
                                      QuerySectorFromCluster(root_clus, NULL),
                                      cluster_size)) {
            Message->Set(MSG_CHK_NO_MEMORY);
            Message->Display();
            return FALSE;
        }

        memset(root_secrun.GetBuf(), 0, cluster_size * sector_size);

        if (root_secrun.Write() && root_secrun.Read()) {
            SetFat32RootDirStartingCluster(root_clus);
            //
            //  Set the bit for the new root in the bit map.
            //
            FatBitMap->SetBit(root_clus);

            //
            //  Reinitialize the FAT32 root directory
            //
            if ( !_hmem_F32->Initialize() ||
                 !_dirF32->Initialize( _hmem_F32, _drive, this,
                                       _fat, root_clus)) {
                Message->Set(MSG_CHK_NO_MEMORY);
                Message->Display();
                return FALSE;
            }


            Report->ExitStatus = CHKDSK_EXIT_ERRS_FIXED;
            return TRUE;
        } else {
            _fat->SetClusterBad(root_clus);
        }

    }

    DebugPrintTrace(("FAT_SA::RelocateNewFat32RootDirectory: This line should not be reached.\n"));
    return FALSE;
}


BOOLEAN
FAT_SA::PerformEaLogOperations(
    IN      ULONG       EaFileCn,
    IN      FIX_LEVEL   FixLevel,
    IN OUT  PMESSAGE    Message,
    IN OUT  PBOOLEAN    NeedErrorsMessage
    )
/*++

Routine Description:

    This routine reads the EA file log from the disk and then performs
    any logged operations specified.

Arguments:

    EaFileCn         - Supplies the first cluster of the EA file.
    FixLevel            - Supplies the fix level.
    Message             - Supplies an outlet for messages.
    NeedErrorsMessage   - Supplies whether or not an error has occurred
                          under check only conditions.

Return Value:

    FALSE   - Failure.
    TRUE    - Success.

--*/
{
    HMEM            hmem;
    EA_HEADER       ea_header;
    PEA_FILE_HEADER pea_header;
    ULONG           cluster_size;
    ULONG           num_clus;

    cluster_size = _drive->QuerySectorSize()*QuerySectorsPerCluster();
    num_clus = sizeof(EA_FILE_HEADER) + BaseTableSize*sizeof(USHORT);
    if (num_clus%cluster_size) {
        num_clus = (num_clus/cluster_size + 1);
    } else {
        num_clus = (num_clus/cluster_size);
    }

    if (!hmem.Initialize() ||
        !ea_header.Initialize(&hmem, _drive, this, _fat, EaFileCn, num_clus) ||
        !(pea_header = ea_header.GetEaFileHeader())) {
        Message->Set(MSG_CHK_NO_MEMORY);
        Message->Display();
        return FALSE;
    }

    if (!ea_header.Read()) {
        Message->Set(MSG_CHK_CANT_CHECK_EA_LOG);
        Message->Display();
        return TRUE;
    }

    if (pea_header->Signature != HeaderSignature ||
        pea_header->FormatType ||
        pea_header->LogType) {
        dofmsg(Message, NeedErrorsMessage);
        Message->Set(MSG_CHK_BAD_LOG, NORMAL_MESSAGE, TEXT_MESSAGE);
        Message->Display();
        if (Message->IsYesResponse(TRUE)) {
            pea_header->Signature = HeaderSignature;
            pea_header->Cluster1 = 0;
            pea_header->Cluster2 = 0;
            pea_header->Cluster3 = 0;

            if (FixLevel != CheckOnly) {
                ea_header.Write();
            }

            return TRUE;
        } else {
            return FALSE;
        }
    }

    if (pea_header->Cluster1) {
        if (_fat->IsInRange(pea_header->Cluster1) &&
            _fat->IsInRange(pea_header->NewCValue1)) {
            _fat->SetEntry(pea_header->Cluster1, pea_header->NewCValue1);
        } else {
            dofmsg(Message, NeedErrorsMessage);
            Message->Set(MSG_CHK_ERROR_IN_LOG);
            Message->Display();
        }
    }

    if (pea_header->Cluster2) {
        if (_fat->IsInRange(pea_header->Cluster2) &&
            _fat->IsInRange(pea_header->NewCValue2)) {
            _fat->SetEntry(pea_header->Cluster2, pea_header->NewCValue2);
        } else {
            dofmsg(Message, NeedErrorsMessage);
            Message->Set(MSG_CHK_ERROR_IN_LOG);
            Message->Display();
        }
    }

    if (pea_header->Cluster3) {
        if (_fat->IsInRange(pea_header->Cluster3) &&
            _fat->IsInRange(pea_header->NewCValue3)) {
            _fat->SetEntry(pea_header->Cluster3, pea_header->NewCValue3);
        } else {
            dofmsg(Message, NeedErrorsMessage);
            Message->Set(MSG_CHK_ERROR_IN_LOG);
            Message->Display();
        }
    }
    return TRUE;
}


PEA_INFO
FAT_SA::RecoverEaSets(
    IN      ULONG       EaFileCn,
    OUT     PUSHORT     NumEas,
    IN      FIX_LEVEL   FixLevel,
    IN OUT  PMESSAGE    Message,
    IN OUT  PBOOLEAN    NeedErrorsMessage
    )
/*++

Routine Description:

    This routine validates and if necessary recovers the EA file.

Arguments:

    EaFileCn            - Supplies the cluster number for the EA file.
    NumEas              - Returns the number of EA sets in the EA file.
    FixLevel            - Supplies the CHKDSK fix level.
    Message             - Supplies an outlet for messages.
    NeedErrorsMessage   - Supplies whether or not an error has occurred
                          under check only conditions.

Return Value:

    An allocated array containing 'NumberOfEaSets' entries documenting
    important information about the EA sets.  If there are no EAs then
    'NumberOfEaSets' is returned as 0 and NULL is returned.  If there
    is an error then NULL will be returned with a non-zero
    'NumberOfEaSets'.

--*/
{
    PEA_INFO    ea_infos;
    ULONG       clus, prev;
    USHORT      num_eas;
    ULONG       i;
    ULONG       length;

    DebugAssert(NumEas);

    *NumEas = 1;

    length = _fat->QueryLengthOfChain(EaFileCn);
    ea_infos = NEW EA_INFO[length];
    if (!ea_infos) {
        Message->Set(MSG_CHK_NO_MEMORY);
        Message->Display();
        return NULL;
    }

    memset(ea_infos, 0, length*sizeof(EA_INFO));

    //
    // Scan file for EA sets and validate them while updating the
    // array.
    //
    num_eas = 0;
    prev = EaFileCn;
    while (!_fat->IsEndOfChain(prev)) {

        clus = VerifyAndFixEaSet(prev, &ea_infos[num_eas], FixLevel,
                                 Message, NeedErrorsMessage);

        if (clus) {
            num_eas++;
        } else {
            clus = _fat->QueryEntry(prev);
        }

        prev = clus;
    }

    if (!num_eas) {

        // All the ea sets are unused, the ea file is
        // effectively empty.

        // Should use array delete instead.
        // DELETE( ea_infos );
        delete [] ea_infos;

        // Free the cluster chain occupied by the ea file
        // so subsequent checking and fixing will not
        // complain about the lost chain in the ea file.

        _fat->FreeChain(EaFileCn);

        ea_infos = NULL;
        *NumEas = 0;
        return NULL;
    }


    // Go through and remove unused portions of the EA file.

    for (i = 0; i < (USHORT)(num_eas - 1); i++) {
        if (ea_infos[i].LastCn != ea_infos[i + 1].PreceedingCn) {

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

            dofmsg(Message, NeedErrorsMessage);

            Message->Set(MSG_CHK_UNUSED_EA_PORTION);
            Message->Display();

            ea_infos[i + 1].PreceedingCn = ea_infos[i].LastCn;
        }
    }

    if (!_fat->IsEndOfChain(ea_infos[num_eas - 1].LastCn)) {

        _fat->SetEndOfChain(ea_infos[num_eas - 1].LastCn);

        dofmsg(Message, NeedErrorsMessage);

        Message->Set(MSG_CHK_UNUSED_EA_PORTION);
        Message->Display();
    }


    // Sort the EAs in the EA file.

    if (!EaSort(ea_infos, num_eas, Message, NeedErrorsMessage)) {
        return NULL;
    }

    *NumEas = num_eas;

    return ea_infos;
}


ULONG
FAT_SA::VerifyAndFixEaSet(
    IN      ULONG       PreceedingCluster,
    OUT     PEA_INFO    EaInfo,
    IN      FIX_LEVEL   FixLevel,
    IN OUT  PMESSAGE    Message,
    IN OUT  PBOOLEAN    NeedErrorsMessage
    )
/*++

Routine Description:

    This routine attempts to identify the clusters following the
    'PreceedingCluster' as an EA set.  If this routine does not
    recognize these clusters as an EA set then it will return 0.
    Otherwise, it will return the last cluster of the validated EA set.

    Changes may be made to the clusters if they are recognized as an EA
    set with errors.

Arguments:

    PreceedingCluster   - Supplies the cluster preceeding the EA set cluster.
    Info                - Returns information about the EA set.
    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:

    The cluster number of the last cluster in the EA set or 0.

--*/
{
    HMEM    hmem;
    EA_SET  easet;
    ULONG   clus;
    PEA_HDR eahdr;
    LONG    i;
    ULONG   j;
    ULONG   need_count;
    LONG    total_size;
    LONG    size;
    ULONG   length;
    BOOLEAN need_write;
    PEA     pea;
    BOOLEAN more;
    ULONG   chain_length;

    clus = _fat->QueryEntry(PreceedingCluster);
    chain_length = _fat->QueryLengthOfChain(clus);

    length = 1;
    need_write = FALSE;

    if (!hmem.Initialize() ||
        !easet.Initialize(&hmem, _drive, this, _fat, clus, length) ||
        !(eahdr = easet.GetEaSetHeader())) {

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

    if (!easet.Read()) {
        return 0;
    }

    if (!easet.VerifySignature()) {
        return 0;
    }

    need_count = 0;
    total_size = 4;
    for (i = 0; ; i++) {
        for (j = 0; !(pea = easet.GetEa(i, &size, &more)) && more &&
                     length + j < chain_length; ) {
            j++;
            if (!hmem.Initialize() ||
                !easet.Initialize(&hmem, _drive, this, _fat, clus, length + j)) {

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

            if (!easet.Read()) {
                return 0;
            }
        }

        if (pea) {
            length += j;
        } else {
            break;
        }

        total_size += size;

        if (pea->Flag & NeedFlag) {
            need_count++;
        }
    }

    if (!i) {
        return 0;
    }

    if (total_size != eahdr->TotalSize) {
        dofmsg(Message, NeedErrorsMessage);
        Message->Set(MSG_CHK_EASET_SIZE);
        Message->Display("%d", clus);
        eahdr->TotalSize = total_size;
        need_write = TRUE;
    }

    if (need_count != eahdr->NeedCount) {
        dofmsg(Message, NeedErrorsMessage);
        Message->Set(MSG_CHK_EASET_NEED_COUNT);
        Message->Display("%d", clus);
        eahdr->NeedCount = need_count;
        need_write = TRUE;
    }

    EaInfo->OwnHandle = eahdr->OwnHandle;
    EaInfo->PreceedingCn = PreceedingCluster;
    EaInfo->LastCn = _fat->QueryNthCluster(PreceedingCluster, length);
    memcpy(EaInfo->OwnerFileName, eahdr->OwnerFileName, 14);
    EaInfo->UsedCount = 0;

⌨️ 快捷键说明

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